.TITLE REQSB .IDENT /15.04/ ; ; Copyright (c) 1995-1999 by Mentec Inc., U.S.A. ; All rights reserved. ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; D. N. CUTLER 10-AUG-73 ; ; MODIFIED FOR RSX-11M-PLUS V2.1: ; ; H. HUANG ; J. R. KAUFFMAN ; B. KRISHNAMURTHY ; J. M. LAWLER ; T. LEKAS ; T. M. MARTIN ; B. S. MCCARTHY ; ; MODIFIED FOR RSX-11M-PLUS VERSION 3.0 BY: ; ; J. M. LAWLER ; J. R. KAUFFMAN ; J. W. BERZLE ; B. S. MCCARTHY ; L. B. MCCULLEY ; ; MODIFIED FOR RSX-11M-PLUS VERSION 4.0 BY: ; ; J. W. BERZLE ; K. L. NOEL ; ; MODIFIED FOR RSX-11M-PLUS VERSION 4.1 BY: ; ; K. L. NOEL ; P. K. M. WEISS ; ; MODIFIED FOR RSX-11M-PLUS VERSION 4.2 BY: ; ; B. S. MCCARTHY ; ; MODIFIED FOR RSX-11M-PLUS V4.3 BY: ; ; J. C. FRANZINI ; K. L. NOEL ; ; MODIFIED FOR RSX-11M-PLUS VERSION 4.5 BY: ; ; D. Carroll 20-June-1989 15.02 ; ; DC114 - Modify mP scheduling algorithm to take into ; consideration possible URM conflicts ; ; D. Carroll 19-Sep-1993 15.03 ; ; DC238 - Allow P/OS checkpointing algorithm to be selected ; on standard RSX-11M-PLUS systems. ; ; Modified for RSX-11M-PLUS V4.6 by: ; ; D. Carroll 18-Oct-1995 15.04 ; DC404 - Include PSECT statement to allow ICB pool to be ; fully extended during sysgen ; ; ; TASK REQUEST RELATED SUBROUTINES ; ; MACRO LIBRARY CALLS ; .MCALL HDRDF$,ITBDF$,PCBDF$,TCBDF$,BGCK$A .IF DF N$$DIR .MCALL LNMDF$ LNMDF$ ;DEFINE CONTEXT BLOCK OFFSETS .ENDC ;DF N$$DIR HDRDF$ ;DEFINE TASK HEADER OFFSETS ITBDF$ ;DEFINE INTERRUPT TRANSFER BLOCK OFFSETS PCBDF$ ;DEFINE PARTITION CONTROL BLOCK OFFSETS TCBDF$ ,,SYSDEF ;DEFINE TASK CONTOL BLOCK OFFSETS & LGTH .IF DF A$$CNT .MCALL ACNDF$ ACNDF$ ;ACCOUNTING OFFSETS .ENDC .IF DF C$$RTK .MCALL CPRDF$ CPRDF$ .ENDC MAP6=140000 .IIF DF,K$$DAS&I$$CBP, .PSECT EXEC1 ;DC404 ;DC404 ;+ ; **-$ABCTK-ABORT CURRENT TASK ; **-$ABTSK-ABORT TASK ; ; THIS ROUTINE IS CALLED TO MARK A TASK FOR ABORT AND TO FORCE A TASK EXIT. ; THE REASON FOR ABORT AND THE CURRENT OUTSTANDING I/O COUNT ARE STORED ; IN THE FIRST TASK EVENT FLAG WORD. ; ; INPUTS: ; ; R0=REASON FOR ABORT. ; R2=EXTENDED ABORTER INFORMATION (VALID ONLY IF R0=S.CABO OR S.CPMD) ; ; OUTPUTS: ; ; THE TASK IS MARKED FOR ABORT AND A CONDITIONAL SCHEDULE REQUEST IS ; SET. ;- $ABCTK::MOV $TKTCB,R1 ;SET TCB ADDRESS TO CURRENT TASK $ABTSK::BIC #TS.STP,T.STAT(R1) ;REMOVE POSSIBLE MCR BLOCK BIT .IF DF C$$RTK ;IF REMOTE TASK SERVICE SUPPORTED BIT #T4.P0,T.ST4(R1);DOES THIS TASK HAVE AN ASSOCIATED P0 IMAGE? BEQ 3$ ;NOPE, CONTINUE WITH NORMAL ABORT PROCESSING MOV R0,-(SP) ;SAVE ABORT CODE MOV R1,-(SP) ;SAVE TCB MOV R2,-(SP) ;SAVE ABORTER INFORMATION MOV #MAP6,R2 ;BASE ADDRESS FOR PACKET MOV $CPOUT,R0 ;GET FIRST OUTSTANDING PACKET 101$: BEQ 25$ ;IF NONE, LEAVE IT ALONE MOV R0,@#KISAR6 ;MAP THE PACKET CMP R1,H$TCB(R2) ;IS THIS THE CORRECT TCB? BNE 1$ ;NO CMPB #HT$VMS,H$TYPE(R2) ;IS THIS THE RIGHT PACKET? BEQ 2$ ;YES, SEND THE P0 ABORT PACKET 1$: MOV H$LINK(R2),R0 ;GET THE NEXT PACKET IN THE LIST BR 101$ ;GO BACK TO CHECK IT OUT 2$: DEC (R2) ;DECREMENT THE LENGTH OF THE P0 BLOCK CLR -(SP) ;GET A STORAGE SPACE MOVB (R2),(SP) ;GET THE LENGTH OF THE BLOCK ADD (SP)+,R0 ;GET THE NEW PACKET BIAS MOV R0,@#KISAR6 ;MOVE TO LAST BLOCK OF ORIGINAL REQUEST MOV #1,(R2) ;LENGTH OF ONE BLOCK MOVB #HT$AP0,H$TYPE(R2) ;SET P0 ABORT TYPE MOV $TKTCB,-(SP) ;SAVE CURRENT TASK MOV R1,$TKTCB ;MOVE IN TASK WE'RE ABORTING CPSEN$ #SN$DET,R0,#H$SIZE ;SEND P0 ABORT REQUEST MOV (SP)+,$TKTCB ;RESTORE CURRENT TASK 25$: MOV (SP)+,R2 ;RESTORE ABORTER INFORMATION MOV (SP)+,R1 ;RESTORE TCB MOV (SP)+,R0 ;RESTORE ABORT CODE 3$: .ENDC ;C$$RTK CMP R0,#S.CABO ;ABORT BY DIRECTIVE OR MCR BEQ 4$ ;IF EQ YES CMP R0,#S.CTKN ;QUIET TASK ABORT? BEQ 4$ ;IF EQ YES, ISSUE ABORT ASTS IF ANY CMP R0,#S.CPMD ;ABORT WITH PMD? BNE 7$ ;IF NE NO 4$: SAVNR ;SAVE R4 AND R5 MOV #AS.REA,R4 ;GET CODE FOR REQUESTED EXIT AST MOV R1,-(SP) ;SAVE TCB ADDRESS MOV R0,-(SP) ;SAVE ABORT CODE MOV R2,-(SP) ;SAVE ABORTER INFORMATION MOV R1,R5 ;COPY TCB ADDRESS CALL $DASTT ;DECLARE AST MOV (SP)+,R2 ;RESTORE ABORTER INFORMATION MOV (SP)+,R0 ;RESTORE ABORT CODE BCC 5$ ;IF CC AST SET UP MOV (SP)+,R1 ;RESTORE TCB ADDRESS BIT #T3.PRV,T.ST3(R1) ;IS TASK PRIVILEGED? BEQ 7$ ;IF EQ NO BIT #T2.REX,T.ST2(R1) ;HAS ABORT AST ALREADY OCCURRED? BEQ 7$ ;IF EQ NO MOV R1,R0 ;COPY TCB ADDRESS BR 10$ ;RESCHEDULE TASK 5$: TST (SP)+ ;CLEAN STACK MOV #4,A.PRM(R1) ;STORE NUMBER OF AST PARAMETER BYTES MOV R2,A.PRM+2(R1) ;STORE ABORTER INFORMATION RETURN ;$NXTSK ALREADY CALLED, SIMPLY RETURN 7$: BIT #T3.ACP,T.ST3(R1) ;ACP ABORTING? BEQ 8$ ;IF EQ NO BIT #T3.PMD,T.ST3(R1) ;IS PMD REQUESTED? BNE 8$ ;IF NE NO (NOTE: T3.PMD=1 MEANS NO PMD) BGCK$A BF.XIT,BE.ACP,FATAL ;CRASH SYSTEM ON ACP ABORTS 8$: MOV R0,T.EFLG(R1) ;INSERT REASON FOR ABORT MOVB T.IOC(R1),T.EFLG+1(R1) ;SAVE OUTSTANDING I/O COUNT .IF DF M$$PRO CLR T.RRM(R1) ;TASK CAN BE ABORTED ON ANY PROCESSOR .ENDC .IF DF P$$OFF BIT #T3.ACP,T.ST3(R1) ;IS THIS AN ACP? BNE 9$ ;IF NE YES MOV #EX$SEV,T.EFLG+2(R1) ;SET SEVERE ERROR EXIT STATUS 9$: ;REFERENCE SYMBOL .ENDC MOV R1,R0 ;COPY TCB ADDRESS ADD #T.STAT,R1 ;POINT TO FIRST TASK STATUS WORD BIC #TS.CKR,(R1)+ ;CLEAR STATUS BITS BIC #T2.SEF!T2.STP!T2.SPN,(R1) ;MAKE TASK RUNNABLE BIS #T2.AST!T2.DST!T2.HLT!T2.ABO,(R1) ;DSBL AST'S & FRC EXIT .IF DF M$$PRO BIT #^C,-(R1) ;OUT FOR INITIAL LOAD OR BLOCKED? .IFF TST -(R1) ;OUT FOR INITIAL LOAD OR OTHERWISE BLKD? .ENDC BNE 10$ ;IF NE YES CALL $SETCR ;SET A CONDITIONAL SCHEDULE REQUEST 10$: MOV T.PCB(R0),R0 ;POINT TO TASK PCB CALLR $NXTSK ;REALLOCATE TASK PARTITION IF NECESSARY ;+ ; **-$BILDS-BUILD STACK AND INITIALIZE HEADER ; ; THIS ROUTINE SETS UP THE TASK STACK AND INITIALIZES THE HEADER. IT IS ; CALLED PRIOR TO PLACING A TASK INTO CONTENTION FOR THE PROCESSOR WHEN ; AN EXECUTION REQUEST IS MADE FOR A TASK THAT IS FIXED IN MEMORY OR ; WHEN A DISK RESIDENT TASK HAS FINISHED LOADING. ; ; INPUTS: ; ; R0=ADDRESS OF THE TCB OF THE TASK TO INITIALIZE. ; ; OUTPUTS: ; ; 1-TASK LOCAL EVENT FLAGS 1.-32. ARE CLEARED. ; 2-CURRENT UIC IS SETUP IN THE HEADER. ; 3-TASK CONTEXT IS SETUP TO CAUSE THE TASK TO START EXECUTION AT ITS ENTR ; 4-REDISPATCHING OF THE PROCESSOR IS CONDITIONALLY REQUESTED. ; ; R3 IS PRESERVED ACROSS CALL. ;- $BILDS::MOV T.PCB(R0),R1 ;GET ADDRESS OF TASK PCB .IF DF X$$HDR MOV KISAR6,-(SP) ;SAVE CURRENT MAPPING FOR XTRNL HDR MOV P.HDR(R1),-(SP) ;SAVE HEADER POINTER BNE 5$ ;IF NE INTERNAL HEADER MOV P.REL(R1),KISAR6 ;MAP TO EXTERNAL HEADER MOV #140000,(SP) ;RESET VIRTUAL ADDRESS OF HEADER 5$: MOV (SP)+,R1 ;GET VIRTUAL ADDRESS OF HEADER .IFF ; DF X$$HDR MOV P.HDR(R1),R1 ;GET ADDRESS OF TASK HEADER .ENDC ; DF X$$HDR MOV T.EFLG(R0),H.CUIC(R1) ;SET SPECIFIED UIC BNE 10$ ;IF NE UIC WAS SPECIFIED MOV H.DUIC(R1),H.CUIC(R1) ;SET DEFAULT UIC .IF DF M$$MUP BR 15$ ; .IFTF 10$: ;REF LABEL .IFT MOV T.ACTL(R0),H.DUIC(R1) ;SET DEFAULT UIC .ENDC 15$: ; .IF DF A$$CNT MOV KISAR5,-(SP) ;SAVE MAPPING MOV T.ACN(R0),KISAR5 ;MAP FIRST ACCOUNTING BLOCK BEQ 16$ ;IF EQ, NO ACCOUNTING ON TASK CMPB #BT.TAB,@#B.TYP+120000 ;IS THIS A TAB BNE 16$ ;IF NE NO MOV H.CUIC(R1),@#B.PUIC+120000 ;COPY PROTECTION UIC MOV H.DUIC(R1),@#B.CUIC+120000 ;COPY CURRENT UIC MOV T.ST3(R0),@#B.TST3+120000 ;COPY T.ST3 16$: MOV (SP)+,KISAR5 ;RESTORE MAPPING .ENDC ;A$$CNT BIT #T2.ABO,T.ST2(R0) ;TASK MARKED FOR ABORT BNE 20$ ;IF NE YES .IF DF M$$PRO MOV T.PCB(R0),R2 ;GET TASK REGION PCB ADDRESS MOV T.RRM(R0),P.RRM(R2) ;SAVE THE TASK'S INSTALLED AFFINITY CALL $SETAT ;SET UP THE TASK'S RUNNING AFFINITY .ENDC CLR T.EFLG(R0) ;CLEAR TASK LOCAL EVENT FLAGS BIT #T3.ACP,T.ST3(R0) ;TASK ACP? BNE 17$ ;IF NE YES CLR T.EFLG+2(R0) ; 17$: ;REFERENCE SYMBOL .IF DF M$$PRO CALL $TSTAT ;ARE THE REQUIRED BUS RUNS PRESENT? BCC 20$ ;IF CC YES MOV R0,-(SP) ;SAVE REGISTERS MOV R1,-(SP) ; MOV R3,-(SP) ; MOV R0,R1 ;COPY TCB ADDRESS MOV #S.CAFF,R0 ;GET TKTN ABORT CODE CALL $ABTSK ;ABORT THE TASK MOV (SP)+,R3 ;RESTORE REGISTERS MOV (SP)+,R1 ; MOV (SP)+,R0 ; .ENDC 20$: MOV H.ISP(R1),(R1) ;SET INITIAL STACK POINTER MOV H.GARD(R1),R2 ;POINT TO CONTEXT SAVE AREA SUB #16,R2 ;POINT TO SAVED PC MOV H.IPC(R1),(R2) ;SET INITIAL PC WORD MOV H.IPS(R1),-(R2) ;SET INITIAL PS WORD .IF DF C$$RTK ;REMOTE TASK BIT #F5.RTK,$FMSK5 ;ARE REMOTE TASKS BEING USED BEQ 30$ ;IF EQ NO TSTB T.TKI(R0) ;HAS THIS TASK HAD CONTACT WITH CPRAME? BEQ 30$ ;IF EQ, NO - DON'T NEED TO CLEAR LUN TABLE CLRB T.TKI(R0) ;INDICATE THAT NO TASK START REQUEST HAS BEEN ; MADE FOR THIS TASK YET .IF DF C$$RTB ;RUN TIME BINDING BIT #F5.RTB,$FMSK5 ;RUN TIME BINDING TURNED ON? BEQ 30$ ;IF EQ NO MOV T.PCB(R0),R3 ;GET PCB ADDRESS BIT #PS.FXD,P.STAT(R3) ;IS TASK FIXED? BEQ 30$ ;IF EQ NO, NO NEED TO CLEAR LUN TABLE MOV R0,-(SP) ;SAVE R0 MOV R5,-(SP) ; AND R5 MOV R3,-(SP) ; AND R3 MOV R0,R5 ;PUT TCB ADDRESS WHERE $MPLND WANTS IT ADD #H.NLUN,R1 ;POINT TO LUN TABLE MOV (R1)+,R3 ;GET NUMBER OF LUNS 25$: MOV (R1),R0 ;GET LUN ASSIGNMENT BEQ 27$ ;IF EQ, NOT ASSIGNED CALL $MPLND ;FOLLOW REDIRECTS CMP (R0),$XXLOW ;MIGHT IT BE A GENERIC DEVICE? BLO 27$ ;IF LO, NO CMP (R0),$XXHGH ;IS IT A GENERIC DEVICE? BHI 27$ ;IF HI, NO 26$: CLR (R1)+ ;CLEAR LUN ENTRY CLR (R1)+ ; SOB R3,25$ ;LOOP UNTIL DONE BR 28$ ;DONE 27$: CMP (R1)+,(R1)+ ;SKIP OVER THIS ONE SOB R3,25$ ;LOOP UNTIL DONE 28$: MOV (SP)+,R3 ;RESTORE R3 MOV (SP)+,R5 ; AND R5 MOV (SP)+,R0 ; AND R0 .ENDC ;C$$RTB 30$: .ENDC ;C$$RTK .IF DF X$$HDR MOV (SP)+,KISAR6 ;RESTORE PREVIOUS MAPPING .ENDC ; DF X$$HDR ;+ ; **-$ACTTK-PUT TASK IN ACTIVE TASK LIST ; ; THIS ROUTINE IS CALLED TO PUT AN ACTIVE TASK IN THE ACTIVE TASK LIST. ; ; INPUTS: ; ; R0=ADDRESS OF THE TCB OF THE TASK TO PUT IN THE ACTIVE LIST. ; ; OUTPUTS: ; THE SPECIFIED TASK IS MERGED INTO THE ACTIVE TASK LIST BY ; PRIORITY. ; ; R3 IS PRESERVED ACROSS CALL. ;- $ACTTK::MOV #$ACTHD-T.ACTL,R1 ;SET ADDRESS OF PREVIOUS TCB 10$: MOV R1,R2 ;SAVE ADDRESS OF PREVIOUS TCB MOV T.ACTL(R2),R1 ;GET ADDRESS OF NEXT TCB CMPB T.PRI(R1),T.PRI(R0) ;TASK HIGHER OR SAME PRIORITY? BHIS 10$ ;IF HIS YES MOV R0,T.ACTL(R2) ;LINK NEW TASK TO PREVIOUS MOV R1,T.ACTL(R0) ;SET LINK TO NEXT IN NEW TASK ;+ ; **-$SETCR-SET CONDITIONAL SCHEDULE REQUEST ; **-$SETRQ-SET SCHEDULE REQUEST ; **-$SETRT-SET SCHEDULE REQUEST FOR CURRENT TASK ; ; THIS ROUTINE IS CALLED TO FORCE REDISPATCHING OF THE PROCESSOR ; FROM A SPECIFIED POSITION IN THE TASK LIST. IF A PREVIOUS REQUEST ; HAS BEEN SET, THEN REDISPATCHING STARTS AT WHICH EVER REQUEST ; HAS THE HIGHEST PRIORITY. ; ; INPUTS: ; ; IF ENTRY AT $SETRT, THEN ; R5=ADDRESS OF THE TCB OF THE CURRENT TASK. ; IF ENTRY AT $SETRQ OR $SETCR, THEN ; R0=ADDRESS OF THE TCB TO START DISPATCHING AT. ; ; OUTPUTS: ; ; A SCHEDULE REQUEST IS SET WHICH WILL FORCE A REDISPATCH- ; ING OF THE PROCESSOR WHEN A SYSTEM EXIT IS EXECUTED. ; ; R2 AND R3 ARE PRESERVED ACROSS CALL. ; R0 IS PRESERVED ACROSS CALL IF ENTRY IS NOT AT $SETRT. ;- .IF NDF M$$PRO .ENABL LSB $SETCR::CMP R0,$TKTCB ;REQUESTED TASK SAME AS CURRENT? BEQ $SETRQ ;IF EQ YES CMPB @$CURPR,T.PRI(R0) ;CURRENT TASK OF HIGHER PRIORITY BHI 30$ ;IF HI YES BLO $SETRQ ;IF LO NO 10$: CALLR $DRDSE ;SAME PRIORITY-DECLARE SIGNIFICANT EVENT $SETRT::MOV R5,R0 ;SET ADDRESS OF DISPATCH TCB $SETRQ::MOV @$RQSCH,R1 ;GET PREVIOUS SCHEDULE REQUEST BEQ 20$ ;IF EQ NO PREVIOUS REQUEST CMP R0,R1 ;TASK ALREADY RESCHEDULED? BEQ 30$ ;IF EQ YES CMPB T.PRI(R1),T.PRI(R0) ;COMPARE PRIORITIES BHI 30$ ;IF HI PREVIOUS IS HIGHER PRIORITY BEQ 10$ ;IF EQ SAME PRIORITY 20$: MOV R0,@$RQSCH ;SET SCHEDULE REQUEST 30$: RETURN ; .DSABL LSB .IFF ;NDF,M$$PRO .ENABL LSB ;+ ; Search for lowest priority rescheduled or currently executing task. ; If it is lower than reschedule request, then force a reschedule ; request for that processor, URM's allowing ... ;- $SETCR::MOV R2,-(SP) ; Save R2 BIT #TS.RUN,T.STAT(R0) ; Is task running on another CPU BNE 40$ ; If NE, yes 5$: MOV #$RQTAB,R2 ; Point to reschedule table MOV #377,-(SP) ; Initialize lowest priority cell with ; maximum possible priority value 10$: MOV (R2)+,-(SP) ; Push next reschedule pointer BNE 15$ ; If NE, there is a reschedule pointer MOV R2,(SP) ; Copy pointer into $RQSCH table ADD #$PRTAB-$RQTAB-T.PRI-2,(SP) ; Convert into pointer into ; priority table 15$: BIT $BTMSK-$RQTAB-2(R2),$URMST ; Is CPU online? BNE 20$ ; If NE, yes 17$: TST (SP)+ ; Clean stack BR 30$ ; Try for next CPU 20$: BIT $CRMTB-$RQTAB-2(R2),T.RRM(R0) ; Will this processor do? BNE 17$ ; If NE, we're missing something ... CMP R0,-2(R2) ; Task already rescheduled??? BNE 25$ ; If NE, no CMP (SP)+,(SP)+ ; Clean stack prior to BR 80$ ; exit 25$: ADD #T.PRI,(SP) ; Point to task priority MOVB @(SP)+,1(SP) ; Pick up task priority CMPB (SP),1(SP) ; Current priority low or same BLO 30$ ; If LO, yes BHI 27$ ; If HI, no -- don't change low priority ;+ ; Priority is the same as the current lowest. if this is our ; CPU, then we will be new lowest priority processor. if not, ; no change. ;- CMP $RQSCH,R2 ; Is this our CPU? BNE 30$ ; If NE, no -- no change 27$: SWAB (SP) ; Else set new lowest priority MOV R2,R1 ; Save reschedule table pointer 30$: CMP R2,#$RQTAB+ ; at end of table BLO 10$ ; If LO, no CMPB (SP)+,T.PRI(R0) ; Schedule request required? BHI 80$ ; If HI, no BLO 60$ ; If LO, yes 35$: MOV (SP)+,R2 ; Else effect significant event because we ; don't know which TCB comes first ; in ATL CALLR $DRDSE ; exit thru $DRDSE ;+ ; Task is in execution -- Find the processor and perform a ; $SETRQ for that processor. This generalizes the single ; processor $SETCR. ; ; Include verification path to insure that a task is not ; scheduled on an incompatable processor. ;- 40$: MOV #$TKTAB,R1 ; Get start of table 45$: CMP (R1)+,R0 ; Is task active on this CPU? BNE 45$ ; If NE, no -- try next CPU ADD #$RQTAB-$TKTAB-2,R1 ; Point into $RQTAB for $SETRQ BR 50$ ; Enter $SETRQ, already in progress $SETRT::MOV R5,R0 ; Set address of dispatch table $SETRQ::MOV $RQSCH,R1 ; Pick up reschedule table pointer MOV R2,-(SP) ; Save R2 ;+ ; This code sgement is based upon the fact that a task which has ; an incompatable URM will not be allowed to return to user mode on ; a processor which is incompatable, if a reschedule request is pending. ;- 50$: BIT $CRMTB-$RQTAB(R1),T.RRM(R0) ; Will this processor do? BEQ 55$ ; if EQ, yup, continue ... BIT #TS.RUN,T.STAT(R0) ; is the task active on a CPU? BEQ 5$ ; nope, reschedule on another CPU CMP $RQSCH,R1 ; is it active on "this" CPU BNE 80$ ; if NE, nope, do nothing ... MOV $ACTHD,(R1) ; force significant event for this CPU BR 5$ ; and force a reschedule on another CPU 55$: MOV (R1)+,R2 ; Pick up current reschedule pointer BEQ 60$ ; If EQ there is none CMP R0,R2 ; Task already rescheduled? BEQ 80$ ; If EQ, yes CMPB T.PRI(R2),T.PRI(R0) ; Is previous higher BHI 80$ ; If HI, yes -- do nothing BNE 60$ ; If NE, yes -- set reschedule request MOV $ACTHD,-(R1) ; Set significant event for this CPU BR 70$ ; Exit thru notification code 60$: MOV R0,-(R1) ; Set reschedule request ;+ ; At this point in a multiprocessor system, we have just changed ; the reschedule pointer for some processor. we want to interrupt ; him to inform him of that fact. ;- 70$: CMP $RQSCH,R1 ; Is it us? BEQ 80$ ; If EQ, yes MTPS #PR7 ; Inhibit deadlock LOCK$ $FORKL,SPIN BIS $BTMSK-$RQTAB(R1),$IIPND ; Show someone needs service ULOCK$ $FORKL,SPIN MTPS #0 ; Back to PR0 80$: MOV (SP)+,R2 ; Restore R2 RETURN .DSABL LSB .ENDC ;NDF,M$$PRO ;+ ; **-$SETMG/$SETFG-SET EVENT FLAG AND UNLOCK IF GROUP GLOBAL ; ; THESE ROUTINES SET AN EVENT FLAG AND TAKE CARE OF THE REQUIRED ; SCHEDULING. IF THE EVENT FLAG WAS GROUP GLOBAL, THE USE COUNT ; FOR THAT FLAG'S GROUP GLOBAL CONTROL BLOCK IS DECREMENTED. IF ; THE CONTROL BLOCK IS MARKED FOR DELETE AND THE COUNT GOES TO ; ZERO, IT WILL BE DEALLOCATED. ; ; INPUTS: ; ; R0=EVENT FLAG NUMBER ($SETFG) OR EVENT FLAG MASK ($SETMG). ; R1=EVENT FLAG WORD ADDRESS ($SETMG ONLY). ; R5=TCB ADDRESS FOR WHICH FLAG IS BEING SET. ; ; OUTPUTS: ; ; R0=TCB ADDRESS OF TASK WHOSE FLAG WAS SET ; R3 IS PRESERVED. ; ;- .ENABL LSB $SETMG::CALL $SETM ;SET THE EVENT FLAG BR 5$ ;JOIN COMMON CODE $SETFG::CALL $SETF ;SET THE EVENT FLAG 5$: ;REFERENCE LABEL .IF DF G$$GEF BNE 15$ ;IF NE FLAG WAS COMMON OR GLOBAL DECB T.GGF(R5) ;DECR GRP GLOBAL USE COUNT FOR TASK ADD #,R1 ;POINT TO GROUP GLOBAL USE COUNT ASR R1 ;SHIFT OFF POSSIBLE SECOND GRP GBL FLAG SBC R1 ;IF IT WAS SET SUBTRACT ONE WHICH BECOMES ASL R1 ;THREE WHEN JOINED WITH THE ASR/ASL DEC (R1) ;DECREMENT GROUP GLOBAL USE COUNT BNE 15$ ;IF NE THESE EVENT FLAGS STILL IN USE BITB #GS.DEL,-(R1) ;FLAGS MARKED FOR DELETE? (G.STAT) BEQ 15$ ;IF EQ NO MOV R0,-(SP) ;SAVE TCB ADDRESS MOV R3,-(SP) ;SAVE R3 MOV R4,-(SP) ;SAVE R4 MOVB -(R1),R4 ;GET GROUP NUMBER (G.GRP) CALL $SRGEF ;FIND THESE FLAGS IN GROUP GLOBAL LIST CALL $ELGEF ;ELIMINATE THIS GROUP GLOBAL CONTROL BLK MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R3 ;RESTORE R3 MOV (SP)+,R0 ;RESTORE TCB ADDRESS .ENDC ; DF G$$GEF 15$: RETURN .DSABL LSB ;+ ; **-$SETF/$SETM-SET EVENT FLAG ; ; THESE ROUTINES SET AN EVENT FLAG AND TAKE CARE OF THE REQUIRED ; RESCHEDULING. ; ; INPUTS: ; ; R0=EVENT FLAG NUMBER ($SETF) OR EVENT FLAG MASK ($SETM). ; R1=EVENT FLAG WORD ADDRESS ($SETM ONLY). ; R5=TCB ADDRESS FOR WHICH FLAG IS BEING SET. ; ; OUTPUTS: ; ; R0=TCB ADDRESS OF TASK WHOSE FLAG WAS SET ; R1=EVENT FLAG WORD ADDRESS ; R3 IS PRESERVED. ; ; IF GROUP GLOBAL EVENT FLAGS ARE SUPPORTED: ; Z=0 IF LOCAL OR COMMON EVENT FLAG SET ; Z=1 IF GROUP GLOBAL EVENT FLAG SET ; ;- $SETF:: CALL $CEFI ;CONVERT EVENT FLAG TO MASK AND ADDRESS $SETM:: CLR -(SP) ;CLR GROUP GLOBAL INDICATOR MOV R1,-(SP) ;SAVE EVENT FLAG WORD ADDRESS BIC #1,R1 ;CLEAR GROUP GLOBAL SECOND WORD FLAG BIT #T2.ABO!T2.HLT,T.ST2(R5) ;TASK EXITING OR MARKED FOR ABORT ? BNE 10$ ;IF NE YES, DO NOT TOUCH EVENT FLAG WORD BIS R0,(R1) ;SET THE EVENT FLAG 10$: MOV R5,R0 ;COPY TCB ADDRESS FOR $SETCR TST R1 ;WAS AN EVENT FLAG SPECIFIED BEQ 19$ ;IF EQ NO, DON'T SCHEDULE CMP R1,#$COMEF+2 ;IS IT A COMMON EVENT FLAG BLOS 20$ ;IF LOS YES SUB R5,R1 ;IS IT GROUP GLOBAL? BLO 15$ ;IF LO YES SUB #T.EFLG+2,R1 ;IS IT LOCAL? BLE 18$ ;IF LE YES 15$: DEC 2(SP) ;INDICATE SETTING GROUP GLOBAL FLAG BR 20$ ;JOIN COMMON CODE 18$: ;REF LABEL BIT #T2.SEF,T.ST2(R0) ;TASK IN STOPFOR STATE? BNE 185$ ;IF NE YES TSTB T.TIO(R0) ;OUTSTANDING BUFFERED I/O? BEQ 30$ ;IF EQ NO, DON'T UNSTOP IT BIT #T2.WFR!,T.ST2(R0) ;TASK IN WFR? BEQ 30$ ;IF EQ NO, DON'T UNSTOP IT 185$: BIT T.EFLM(R0),@T.EFLM+2(R0) ;STOPFOR CONDITION SATISFIED? BEQ 30$ ;IF EQ NO, DON'T UNSTOP IT MOV R3,-(SP) ;SAVE R3 MOV R0,-(SP) ;SAVE TCB CALL $EXRQN ;UNSTOP AND REQUEST TASK TO RUN MOV (SP)+,R0 ;RESTORE TCB MOV (SP)+,R3 ;RESTORE R3 19$: TST $SIGFL ;TASK WAITING FOR SIGNIFICANT EVENT? BEQ 30$ ;IF EQ NO 20$: CALL $DRDSE ;DECLARE SIGNIFICANT EVENT BR 40$ ;JOIN COMMON CODE 30$: CALL $SETCR ;FORCE CONDITIONAL REDISPATCH 40$: MOV (SP)+,R1 ;RESTORE EVENT FLAG WORD ADDRESS INC (SP)+ ;CLEAN STACK AND SET Z-BIT FOR RETURN RETURN ; ;+ ; **-$DCAST-DECLARE COMMAND ARRIVAL AST TRAP FOR CLIS ; ; THIS ROUTINE IS CALLED BY THE COMMAND QUEUEING ROUTINE $QCPKT ; WHEN IT IS QUEUEING A COMMAND TO A CLI TASK. IF THE CLI ; HAS SPECIFIED THE COMMAND ARRIVAL AST, AN ATTEMPT IS MADE TO ; ALLOCATE A NEW AST BLOCK FROM THE POOL. THIS IS DONE IN ORDER ; TO ELIMINATE THE WINDOW THAT OCCURS WHEN THE AST BLOCK WOULD ; NORMALLY BE UNLINKED FROM T.SAST AND LINKED INTO T.ASTL. ; IT WOULD BE UNACCEPTABLE FOR A CLI TO LOSE A COMMAND DURING THIS ; WINDOW. IF THE ALLOCATION FAILS HOWEVER, THE CURRENT EXISTING ; AST BLOCK IS USED. THE WORD AT A.PRM+2 IN THE AST BLOCK IS USED ; AS A FLAG TO THE SYSXT CODE TO INFORM IT IF IT SHOULD DEALLOCATE ; OR RELINK THE AST BLOCK. ; ; INPUTS: ; ; R0=TCB ADDRESS OF CLI ; R1=ADDRESS OF COMMAND BUFFER ; ; OUTPUTS: ; ; C=1 IF THE TASK IS NOT SETUP FOR THE SPECIFIED AST ; C=0 IF THE TASK IS SETUP FOR THE AST AND THE AST HAS ; BEEN DECLARED ; R1=ADDRESS OF THE AST CONTROL BLOCK ; ;- .IF DF A$$CLI $DCAST::SAVNR ;SAVE R4 AND R5 MOV #AS.CAA,R4 ;SET AST TYPE MOV R0,R5 ;COPY CLI'S TCB ADDRESS MOV R1,R3 ;COPY COMMAND ADDRESS .IFF ;A$$CLI $DCAST==-1 .ENDC ;A$$CLI ;+ ; **-$DASTT-DECLARE AST TRAP ; ; THIS ROUTINE IS CALLED TO DECLARE A NON-I/O RELATED AST TRAP. THE ; TCB OF THE SPECIFIED TASK IS EXAMINED TO DETERMINE IF THE SPECIFIED ; AST IS ENABLED (SETUP). IF IT IS THEN THE AST IS DECLARED. ; ; INPUTS: ; ; R3=COMMAND ADDRESS IF AST TYPE = AS.CAA ; R4=CODE INDICATING WHICH AST SHOULD BE DECLARED. ; R5=ADDRESS OF THE TCB OF THE TASK TO DECLARE THE AST FOR. ; ; OUTPUTS: ; ; C=1 IF THE TASK IS NOT SETUP FOR THE SPECIFIED AST. ; C=0 IF THE TASK IS SETUP FOR THE AST AND THE AST HAS BEEN DECLARED. ; R1=ADDRESS OF THE AST CONTROL BLOCK. ; ; NOTE: R4 IS DESTROYED BY THIS ROUTINE ;- .ENABL LSB $DASTT::CALL $SRAST ;SEARCH FOR SPECIFIED AST BLOCK BCS 10$ ;IF CS, THERE IS NONE .IF DF A$$CLI CMP A.CBL(R0),# ;DECLARING CMD ARRIVAL AST BNE 1$ ;IF NE NO MOV R1,-(SP) ;SAVE POINTER TO AST BLOCK ADDRESS MOV #C.LGTH,R1 ;GET LENGTH OF AN AST BLOCK CALL $ALOCB ;ALLOCATE ONE FROM THE POOL MOV (SP)+,R4 ;RESTORE POINTER TO AST BLOCK ADDRESS MOV (R4),R1 ;GET ADDRESS OF EXISTING AST BLOCK BCC 105$ ;IF CC, SUCCESSFUL ALLOCATION MOV SP,A.PRM+2(R1) ;NON-ZERO TO FORCE SYSXT TO RELINK MOV (R1),(R4) ;REMOVE AST BLOCK FROM LIST BR 107$ ; 105$: MOV R1,R4 ;COPY POINTER TO OLD BLOCK MOV R0,R1 ;COPY NEW AST BLOCK ADDR CMP (R4)+,(R0)+ ;SKIP LINK WORDS MOV (R4)+,(R0)+ ;COPY A.CBL MOV (R4)+,(R0)+ ;COPY A.BYT MOV (R4)+,(R0)+ ;COPY A.AST MOV (R4)+,(R0)+ ;COPY A.NPR CLR A.PRM+2(R1) ;ZERO TO FORCE SYSXT TO DEALLOCATE 107$: MOV R3,A.PRM(R1) ;SET COMMAND ADDRESS IN AST BLOCK MOV R5,R0 ;SET TCB ADDRESS OF CLI BR $QASTT ;QUEUE AST 1$: .ENDC ;A$$CLI CMPB A.CBL+1(R0),#AS.REA ;IS THIS A REQUESTED EXIT AST? BNE 2$ ;IF NE NO BIS #T2.REX,T.ST2(R5) ;INDICATE AST HAS BEEN DECLARED 2$: MOV (R0),(R1) ;REMOVE THE CONTROL BLOCK FROM THE LIST MOV R0,R1 ;SAVE ADDRESS OF THE AST CONTROL BLOCK MOV R5,R0 ;COPY TCB ADDRESS .IF DF C$$INT BR $QASTT ;GO QUEUE THE AST ;+ ; **-$DQAC-DEQUEUE AST BLOCK QUEUED BY $QASTC. ; (TO BE CALLED FROM SYSXT ONLY). ; ; INPUT: ; R0 POINTER TO AST BLOCK ; ; OUTPUT: ; A.CBL SET TO 1 TO INDICATE AST BLOCK FREE ; (NOT IN AST QUEUE). ; ; REGISTERS ALTERED: NONE ;- $DQAC:: INC A.CBL(R0) ; SET AST BLOCK FREE RETURN ;+ ; **-$QASTC-QUEUE AST TO TASK. ; ; THIS IS A VARIANT OF $QASTT TO BE USED BY A TASK ISR, ENTERED ; VIA A VECTOR CONNECTED TO VIA THE CINT$ DIRECTIVE. ; ; INPUT: ; R5 POINTER TO FORK BLOCK IN ITB ; ; OUTPUT: ; CC-C 0 IF OK, 1 IF AST ADDRESS NOT SPECIFIED IN CINT$ CALL. ; ; NOTE - IF THE AST BLOCK IS ALREADY QUEUED FOR THE TASK, ; NO ACTION IS TAKEN. RETURN CC-C = 0. ; ; REGISTERS ALTERED: R0,R1,R2,R3 ;- $QASTC::MOV R5,R1 ADD #X.AST-X.FORK,R1 ;GET AST BLOCK TST A.CBL(R1) ;AST BLOCK ALREADY IN AST QUEUE? BEQ 10$ ;Y - EXIT WITH CC-C = 0 TST A.AST(R1) ;AST ADDRESS SPECIFIED? SEC ;ASSUME NO BEQ 10$ ;N - EXIT WITH CC-C = 1 CLR A.CBL(R1) ;INDICATE AST BLOCK IN USE MOV X.TCB-X.FORK(R5),R0 ;GET TCB ADDRESS ;FALL THRU TO $QASTT .ENDC ;+ ; **-$QASTT-QUEUE AST TO TASK ; ; THIS ROUTINE IS USED TO QUEUE AN AST TO A TASK AND INSURE THE TASK ; WILL BE SCHEDULED AND RECONSIDERED FOR ELIGIBILITY IN THE PARTITION. ; ; INPUTS: ; ; R0=TCB ADDRESS OF TASK TO RECEIVE AST ; R1=ADDRESS OF AST CONTROL BLOCK TO BE USED ; ; OUTPUTS: ; ; C=0 ; R1 IS PRESERVED ;- $QASTT::ADD #T.ASTL,R0 ;POINT TO TASK AST LISTHEAD MOV R1,-(SP) ;SAVE ADDRESS OF AST CONTROL BLOCK CALL $QINSF ;INSERT CONTROL BLOCK IN AST QUEUE SUB #T.ASTL,R0 ;POINT BACK TO TCB ADDRESS ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 08. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH08==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL CALL @#$SETCR ;SET CONDITIONAL SCHEDULE REQUEST BIT #T2.STP,T.ST2(R0) ;IS TASK STOPPED? BEQ 5$ ;IF EQ NO MOV T.PCB(R0),R0 ;POINT TO TASK PCB CALL $NXTSK ;REALLOCATE TASK PARTITION 5$: MOV (SP)+,R1 ;RESTORE AST CONTROL BLOCK ADDRESS CLC ;RETURN CARRY CLEAR 10$: RETURN ; .DSABL LSB ;+ ; **-$SRAST-SEARCH FOR A SPECIFIED AST BLOCK ; ; THIS ROUTINE IS CALLED TO SEARCH FOR A SPCIFIC TYPE OF AST CONTROL BLK ; ; INPUTS: ; ; R4=CODE INDICATING TYPE OF BLOCK TO BE SEARCHED FOR ; R5=TCB ADDRESS OF TASK WHOSE SAST LIST IS TO BE SEARCHED ; ; OUTPUTS: ; ; C=1 IF SPECIFED TYPE OF AST BLOCK NOT FOUND ; C=0 IF SPECIFIED TYPE OF AST BLOCK IS FOUND ; R0=ADDRESS OF THE BLOCK ; R1=ADDRESS OF WORD POINTING TO THE BLOCK ;- $SRAST::MOV R5,R0 ;GET TCB ADDRESS ADD #T.SAST,R0 ;POINT TO SPECIFIED AST BLOCK ADDRESS 10$: SEC ;ASSUME FAILURE MOV R0,R1 ;GET POINTER TO NEXT BLOCK MOV (R0),R0 ;GET LINK WORD BEQ 20$ ;IF EQ, END OF LIST CMPB R4,A.CBL+1(R0) ;IS THIS THE BLOCK OF THE SPECIFIED TYPE BNE 10$ ;NO IF NE 20$: RETURN ;+ ; **-$SRPRO-SEARCH PROTOTYPE TCB LIST ; ; THIS ROUTINE IS CALLED TO SCAN THE SECONDARY POOL TCB LIST FOR A ; SPECIFIC TASK NAME. IF THE SEARCH SUCCEEDS, THEN THE ADDRESS OF A ; KISAR5 BIAS, WITH THE LOW BIT OF THE ADDRESS SET TO DIFFERENTIATE ; IT FROM A POOL TCB ADDRESS, IS RETURNED. IF THE SEARCH FAILS, THEN ; THE ROUTINE DROPS INTO $SRSTD TO SEARCH THE PRIMARY TCB LIST. ; ; INPUTS: ; ; R3=ADDRESS OF THE TASK NAME TO SEARCH FOR ; ; OUTPUTS: ; ; C=1 IF THE TASK IS NOT IN EITHER TASK LIST ; C=0 IF TASK WAS FOUND ; R0=ADDRESS OF TCB IN POOL (IF EVEN) ; R0=ADDRESS OF KISAR5 BIAS OF TCB ! 1 (IF ODD) ;- $SRPRO:: ;REFERENCE LABEL .IF DF P$$OOL CALL CLIDSP ;CHECK IF TASK NAME WAS CLI... MOV KISAR6,-(SP) ;SAVE APR 6 FOR SCAN MOV $PTCBL,KISAR6 ;MAP TO FIRST TCB IN LIST BEQ 30$ ;IF EQ THERE IS NONE 10$: CMP (R3),140000+T.NAM ;MATCH ON FIRST HALF OF TASK NAME ? BNE 20$ ;IF NE NO CMP 2(R3),140002+T.NAM ;LUCKY SO FAR, SECOND HALF ? BEQ 40$ ;IF EQ YES, THIS IS IT 20$: MOV 140000+T.TCBL,KISAR6 ;MAP TO NEXT TCB IN LIST BNE 10$ ;IF NE NOT END OF LIST 30$: MOV (SP)+,KISAR6 ;PUT APR 6 BACK AS WE FOUND IT BR SCNSTD ;AND TRY THE STD 40$: MOV #$PTCPT,R0 ;POINT TO THE PROTO TCB POINTER MOV KISAR6,(R0) ;STORE KISAR6 BIAS INC R0 ;INDICATE KISAR5 POINTER, NOT TCB ADDRESS MOV (SP)+,KISAR6 ;RESTORE PREVIOUS MAPPING RETURN ;C IS CLR DUE TO CMP ABOVE .ENDC ;DF P$$OOL ;+ ; **-$SRSTD-SEARCH SYSTEM TASK DIRECTORY ; ; THIS ROUTINE IS CALLED TO SEARCH THE TASK DIRECTORY FOR A TASK OF THE ; SPECIFIED NAME. ; ; INPUTS: ; ; R3=ADDRESS OF THE TASK NAME TO SEARCH FOR. ; ; OUTPUTS: ; ; C=1 IF SPECIFIED TASK IS NOT FOUND. ; C=0 IF SPECIFIED TASK IS FOUND. ; R0=ADDRESS OF THE TCB. ; ; R1,R2, AND R3 ARE PRESERVED ACROSS CALL. ;- .ENABL LSB $SRSTD::CALL CLIDSP ;CHECK FOR CLI... SCNSTD: MOV $TSKHD,R0 ;POINT TO FIRST TCB IN LIST 10$: CMP T.NAM(R0),(R3) ;FIRST HALF OF NAME MATCH? BNE 20$ ;IF NE NO CMP T.NAM+2(R0),2(R3) ;SECOND HALF OF NAME MATCH? BEQ 30$ ;IF EQ YES 20$: MOV T.TCBL(R0),R0 ;GET LINK TO NEXT TCB TST T.TCBL(R0) ;NULL TASK? BNE 10$ ;IF NE NO 25$: SEC ;INDICATE FAILURE 30$: RETURN ; ; ; **-CLIDSP-LOCAL ROUTINE TO CHECK IF SUPPLIED TASK NAME IS "CLI..." ; ; THIS ROUTINE IS CALLED BY EITHER $SRPRO OR $SRSTD TO CHECK IF THE ; TASK THEY ARE TRYING TO FIND IS THE CLI DISPATCHER "CLI...". ; IF IT IS, THE ADDRESS OF MCR... IS PUT IN R0, AND A RETURN TO ; THE CALLER'S CALLER IS EXECUTED. OTHERWISE, A RETURN TO THE ; APPROPRIATE SCAN ROUTINE IS EXECUTED TO SEARCH THE LIST. ALL ; THIS IS BEING DONE SINCE THERE IS NO ACTUAL CLI... TASK IN THE SYSTEM. ; CLI... IS INTENDED TO BE USED FROM SPWN$ OR RPOI$ TO PASS A COMMAND ; LINE TO THE TERMINAL'S CLI, WHEREAS MCR... WILL FORCE THE COMMAND ; TO MCR, REGARDLESS OF CLI ASSIGNMENT. ; ; INPUTS: ; ; R3=ADDRESS OF TASK NAME ; ; OUTPUTS: ; ; IF THE NAME WAS CLI..., THE TCB ADDRESS IS RETURNED IN R0 ; WITH C=0 TO THE CALLER'S CALLER. ; IF THE NAME WAS NOT CLI..., A RETURN TO THE CALLER IS EXECUTED. ; ;- CLIDSP: CMP #^RCLI,(R3) ;SEARCHING FOR CLI... BNE 35$ ;IF NE NO CMP #^R...,2(R3) ;MAY HAVE IT BNE 35$ ;IF NE NO MOV $MCRPT,R0 ;USE TCB OF MCR... TST (SP)+ ;POP FIRST RETURN ADDRESS AND SET C=0 35$: RETURN ;+ ; **-$ACTRM-REMOVE TASK FROM THE ACTIVE TASK LIST ; ; THIS ROUTINE IS CALLED TO REMOVE A TCB FROM THE ACTIVE TASK LIST. ; ; INPUTS: ; ; R0=ADDRESS OF THE TCB TO REMOVE. ; ; OUTPUTS: ; ; C=1 IF THERE IS NO ENTRY IN THE LIST THAT MATCHES THE TCB ADDRES ; C=0 IF A MATCHING ENTRY IS REMOVED FROM THE LIST. ; ; R0 IS PRESERVED ACROSS THE CALL. ; ;- $ACTRM::MOV #$ACTHD-T.ACTL,R1 ;GET ADDR OF LISTHEAD 40$: MOV R1,R2 ;SAVE PREVIOUS TCB ADDR MOV T.ACTL(R2),R1 ;GET NEXT TCB ADDR BEQ 25$ ;IF EQ END OF LIST FOUND CMP R0,R1 ;DOES NEXT TCB ADDR EQ OURS? BNE 40$ ;IF NE NO -- KEEP LOOKING MOV T.ACTL(R0),T.ACTL(R2) ;REMOVE ENTRY RETURN ;EXIT .DSABL LSB ;+ ; **-$SRMUT-SEARCH FOR MULTI-USER TASK ; ; THIS ROUTINE CALCULATES THE NAME OF A MULTI-USER TASK ACCORDING TO ; THE NAME OF THE PROTOTYPE TCB AND THE TI: OF THE COPY. IT THEN ; SEARCHES FOR THE COPY OF THE MULTI-USER TASK IN THE TASK LIST. ; ; INPUTS: ; ; R0=ADDRESS OF THE TI: UCB OF THE COPY OF THE MULTI-USER TASK ; R1=FIRST WORD OF THE TASK NAME OF THE COPY OF THE TASK ; ; OUTPUTS: ; ; R3=PTR TO CALCULATED TASK NAME (IN $TNAME AND $TNAME+2). ; ; C=0 IF THE COPY WAS FOUND IN THE TASK LIST ; R0=ITS TCB ADDRESS ; ; C=1 IF THE COPY WAS NOT FOUND IN THE TASK LIST ;- .IF DF R$$DSP $SRMUT::MOV R1,$TNAME ;SET FIRST WORD OF TASK NAME CLR -(SP) ;ALLOCATE SCRATCH SPACE MOV (R0),R2 ;POINT TO TI: DCB TST (R2)+ ;SKIP OVER LINK WORD (D.LNK) SUB (R2)+,R0 ;CALC RELATIVE ADDRESS OF UCB (D.UCB) MOV (R2)+,-(SP) ;PUSH DEVICE NAME OF TI: (D.NAM) MOV (R2)+,-(SP) ;SAVE LOW UNIT NUMBER FOR DCB (D.UNIT) MOV (R2),R1 ;PICK UP SIZE OF UCB (D.UCBL) CALL $DIV ;CALCULATE RELATIVE UNIT NUMBER OF UCB ADD (SP)+,R0 ;CALCULATE LOGICAL UNIT NUMBER OF UNIT BIC #177400,R0 ;CLEAR HIGH BYTE CMP R0,#77 ;IS UNIT GREATER THAN 77? BLOS 9$ ;IF LOS NO MOV R0,R1 ;COPY UNIT NUMBER ASH #-3,R1 ;CALCULATE HIGH ORDER CHARACTER ADD #'A-10,R1 ;CONVERT TO ASCII BIC #177770,R0 ;CALCULATE LOW ORDER CHARACTER ADD #'0,R0 ;CONVERT TO ASCII BR 15$ ; 9$: MOV R0,R1 ;COPY UNIT NUMBER BIC #70,R0 ;MASK OFF HIGH-ORDER DIGIT ADD #'0,R0 ;CONVERT TO ASCII DIGIT ASRB R1 ;CALCULATE HIGH-ORDER DIGIT ASRB R1 ; ASRB R1 ; BNE 10$ ;IF NE THERE IS A HIGH-ORDER DIGIT MOV R0,R1 ;ELSE SUPPRESS HIGH-ORDER ZERO BR 20$ ; 10$: ADD #'0,R1 ;CONVERT TO ASCII DIGIT 15$: MOVB R0,2(SP) ;STORE LOW DIGIT 20$: MOVB R1,1(SP) ;STORE IN SCRATCH SPACE MOV SP,R0 ;POINT TO ASCII TASK NAME CALL $CAT5 ;CONVERT TO RAD50 WORD CMP (SP)+,(SP)+ ;CLEAN STACK MOV #$TNAME,R3 ;POINT TO TASK NAME AREA IN SYSCM MOV R1,2(R3) ;SET SECOND WORD OF TASK NAME CALLR $SRSTD ;SEARCH FOR TASK NAME AND RETURN ;+ ; **-$TCBCP-TCB COPY ROUTINE ; ; THIS ROUTINE IS CALLED TO COPY AN INSTALLED TCB INTO AN ALLOCATED ; TCB AND LINK IT INTO TO THE SYSTEM TASK DIRECTORY. SPECIFICALLY, ; THIS ROUTINE DOES THE FOLLOWING: ; ; 1. COPY THE CONTENTS OF THE INSTALLED TCB INTO THE ALLOCATED TCB. ; 2. INITIALIZE ALL LISTHEADS IN THE ALLOCATED TCB. ; 3. TRANSFER ANY SEND PACKETS DESTINED FOR THE ALLOCATED TCB. ; 4. SET UP THE TASK NAME IN THE NEW TCB. ; 5. LINK THE NEW TCB INTO THE SYSTEM TASK DIRECTORY IMMEDIATELY ; AFTER THE TCB INPUT AS THE PROTOTYPE INSTALLED TCB. ; ; INPUTS: ; ; R0=ADDRESS OF THE ALLOCATED TCB ; R1=ADDRESS OF THE INSTALLED TCB ; IF R1 IS ODD, THEN R1-1 IS THE ADDRESS OF THE KISAR6 BIAS ; OF A PROTOTYPE TCB IN SECONDARY POOL. ; R3=ADDRESS OF THE TASK NAME DOUBLE-WORD FOR THE ALLOCATED TCB ; ; OUTPUTS: ; ; R0 AND R1 ARE PRESERVED. ;- $TCBCP::SAVNR ;SAVE R4 AND R5 .IF DF P$$OOL MOV KISAR6,-(SP) ;SAVE CURRENT KERNEL MAPPING BIT #1,R1 ;IS TCB IN SECONDARY POOL ? BEQ 3$ ;IF EQ NO DEC R1 ;POINT BACK TO BIAS MOV (R1),KISAR6 ;REMAP TO SEC. POOL TCB MOV (R1),(R0)+ ;STORE KISAR6 BIAS IN T.LNK FOR ;POSSIBLE ERROR RECOVERY BY $REMOV MOV #140000,R1 ;POINT TO TCB VIRTUAL ADDRESS BR 4$ ;ENTER COMMON CODE .ENDC ;DF P$$OOL 3$: CLR (R0)+ ;CLEAR AND SKIP LINK WORD (T.LNK) 4$: MOVB T.DPRI(R1),(R0)+ ;INIT RUNNING PRIORITY (T.PRI) CLRB (R0)+ ;INIT I/O COUNT (T.IOC) MOV T.PCBV(R1),(R0)+ ;COPY POINTER TO PCB VECTOR (T.PCBV) BEQ 5$ ;IF EQ THERE IS NONE ADD #400,@T.PCBV(R1) ;INCREMENT ACCESS COUNT IN VECTOR 5$: MOV (R3)+,(R0)+ ;STORE TASK NAME (T.NAM) MOV (R3),(R0)+ ; ADD #T.RCVL,R1 ;POINT TO INSTALLED TCB RCVD LIST CALL 40$ ;SETUP RECEIVE QUEUE 10$: ;MARK T.RCVL CALL CALL @(SP)+ ;SETUP AST QUEUE CLR (R0)+ ;CLEAR EFN WORDS (T.EFLG) CLR (R0)+ ; CMP (R0)+,(R0)+ ;POINT TO STATUS WORDS (T.UCB)(T.TCBL) MOV #TS.EXE,(R0)+ ;INIT FIRST STATUS WORD (T.STAT) ADD #T.ST2-T.EFLG,R1 ;POINT TO INSTALLED TCB 2ND STAT WORD MOV (R1)+,(R0) ;COPY SECOND STATUS WORD (T.ST2) BIC #^CT2.CHK,(R0)+ ;CLEAR ALL BUT CHECKPOINTABILITY (T.ST2) MOV (R1)+,(R0) ;COPY THIRD STATUS WORD (T.ST3) BIC #T3.REM!T3.MCR!T3.CAL,(R0)+ ;CLR NECESSARY BITS (T.ST3) MOV (R1)+,(R0)+ ;(T.DPRI & T.LBN) MOV (R1)+,(R0)+ ;(T.LBN+1) MOV (R1)+,(R0)+ ;(T.LDV) MOV (R1)+,R2 ;PICK UP PCB ADDRESS (T.PCB) MOV P.MAIN(R2),(R0)+ ;SET PCB POINTER (T.PCB) MOV (R1)+,(R0)+ ;(T.MXSZ) CMP (R1)+,(R0)+ ;(T.ACTL) CALL @(SP)+ ;SET UP ATTACHMENT LISTHEAD MOV (R1)+,(R0) ;FOURTH STATUS WORD (T.ST4) BIC #T4.PRO!T4.RIN,(R0)+ ;CLEAR NON-PROPAGATED BITS MOV (R1)+,(R0)+ ;HDR LENGTH/UNUSED BYTE (T.HDLN) CLR (R0)+ ;GRP GBL USE/BUFFERED I/O (T.GGF,T.TIO) TST (R1)+ ;POINT TO T.EFLM MOV (R1)+,(R0)+ ;COPY POSSIBLE CPU TIME LIMIT IN T.EFLM MOV (R1)+,(R0)+ ;SECOND HALF .IF DF A$$CNT BIT #TS.EXE,T.STAT-T.TKSZ(R1) ;IS SOURCE TASK ACTIVE ? BNE 15$ ;IF NE, NO CLR -2(R0) ;YES, THEN DON'T COPY (T.EFLM+2) CLR -4(R0) ;EVENT FLAG MASKS (T.EFLM) 15$: ;REFERENCE LABEL .ENDC ; DF A$$CNT MOV (R1)+,(R0)+ ;TASK INITIAL LOAD SIZE (T.TKSZ) $$$=T.TKSZ+2 .IF DF P$$LAS MOV (R1)+,(R0)+ ;COPY OFFSET WORD (T.OFF) CLR (R0)+ ;CLR SREF WITH EFN COUNT (T.SRCT-1) TST (R1)+ ;ADVANCE INSTALLED TCB POINTER CALL @(SP)+ ;SET UP RECEIVE BY REFERENCE LISTHEAD 20$: ;MARK T.RRFL CALL $$$=T.RRFL+4 ;MARK CURRENT POSITION IN TCB .ENDC .IF DF N$$DIR CLR (R0) ;POINTER TO CONTEXT BLOCK (DDS) (T.CTX) CMP (R0)+,(R1)+ ;INCREMENT TCB POINTERS $$$=T.CTX+2 .ENDC ; DF N$$DIR .IF DF P$$OFF CALL @(SP)+ ;SETUP OCB LISTHEAD CLR (R0) ;CLEAR RUNDOWN COUNT CMP (R0)+,(R1)+ ;ADVANCE TCB POINTERS .ENDC CLR (R0) ;CLEAR T.SAST $$$=T.SAST ;MARK CURRENT POSITION IN TCB .IF DF M$$PRO CMP (R0)+,(R1)+ ;ADVANCE TCB POINTERS TO T.RRM MOV (R1)+,(R0)+ ;COPY REQUIRED RUN MASK MOV (R1)+,(R0)+ ;COPY INITIAL AFFINITY (T.IRM) CLR (R0) ;CLEAR CPU ID AND UNUSED BYTE $$$=T.CPU .ENDC .IF DF A$$CNT CMP (R0)+,(R1)+ ;ADVANCE TCB POINTERS TO T.ACN CLR (R0) ;CLEAR POINTER TO ACCOUNTING BLOCK $$$=T.ACN ;MARK CURRENT POSITION IN TCB .ENDC .IF DF U$$DAS CMP (R0)+,(R1)+ ;ADJUST TCB POINTERS TO T.ISIZ MOV (R1),(R0) ;COPY I SPACE SIZE $$$=T.ISIZ .ENDC ; DF U$$DAS SUB #$$$,R0 ;POINT BACK TO START SUB #$$$,R1 ; .IF DF P$$OOL CMP #140000,R1 ;TCB IN PRIMARY POOL ? BHI 30$ ;IF HI YES MOV #$TSKHD-T.TCBL,R2 ;POINT TO FIRST TCB IN SYSTEM 25$: MOV R2,R1 ;SAVE POINTER TO OLD TCB MOV T.TCBL(R2),R2 ;POINT TO NEXT TCB IN LIST BEQ 30$ ;IF EQ THERE IS NONE CMPB T.DPRI(R2),T.DPRI(R0) ;TASK BELONG BEFORE THIS TCB ? BHIS 25$ ;IF HIS NO,KEEP GOING 30$: ;REFERENCE LABEL .ENDC ; DF P$$OOL MOV T.TCBL(R1),T.TCBL(R0) ;LINK ALLOCATED TCB INTO STD MOV R0,T.TCBL(R1) ; TST (SP)+ ;POP COROUTINE ADDRESS .IF DF P$$OOL MOV (SP)+,KISAR6 ;RESTORE PREVIOUS KERNEL MAPPING .ENDC ; DF P$$OOL RETURN ; 40$: CLR (R0) ;INIT LISTHEAD IN ALLOCATED TCB MOV R0,2(R0) ; .IF DF P$$LAS CMP (SP),#20$ ;IS IT THE RRFL LIST? BEQ 50$ ;IF EQ YES .ENDC CMP (SP),#10$ ;IS IT THE RECEIVE LIST? BNE 80$ ;IF NE NO BIT #T3.NSD!T3.ACP,T.ST3-T.RCVL(R1) ;DOES TASK HAVE ;STANDARD RECEIVE QUEUE ? BNE 80$ ;IF NE, NO - DON'T TRY TO COPY .IF DF P$$OOL MOV R0,-(SP) ;SAVE LISTHEAD ADDRESS FOR ALLOC TCB MOV R1,-(SP) ;SAVE LISTHEAD ADDRESS FOR INS TCB MOV KISAR5,-(SP) ;SAVE KISAR5 MOV R1,R0 ;COPY INSTALLED TCB POINTER MOV R0,R4 ;COPY POINTER 46$: MOV (R4),R4 ;GET NEXT PACKET BEQ 47$ ;IF EQ END OF LIST MOV R4,KISAR5 ;MAP THE PACKET THROUGH APR 5 MOV @#120002,R1 ;GET NUMBER OF DATA WORDS + 2 ASL R1 ;CONVERT TO BYTES ADD #120010,R1 ;POINT TO TASK NAME IN PACKET MOV #120000,R4 ;POINT TO PACKET LINK WORD CMP (R1),-2(R3) ;MATCH ON FIRST WORD OF TASK NAME? BNE 46$ ;IF NE NO CMP 2(R1),(R3) ;MATCH ON SECOND WORD OF TASK NAME? BNE 46$ ;IF NE NO MOV KISAR5,R1 ;GET PACKET ADDRESS MOV 2(SP),R0 ;GET LISTHEAD FOR ALLOCATED TCB CALL $GTSPK ;UNLINK THE PACKET FROM INSTALLED TCB MOV R0,R4 ;SET UP TO RESTART SCAN MOV 4(SP),R0 ;GET INSTALLED TCB LISTHEAD ADDRESS CALL $QSPIF ;AND LINK IT TO ALLOCATED TCB BR 46$ ;CONTINUE SCAN 47$: MOV (SP)+,KISAR5 ;RESTORE KISAR5 MOV (SP)+,R1 ;RESTORE LISTHEAD ADDRESS OF INS TCB MOV (SP)+,R0 ;RESTORE LISTHEAD ADDRESS OF ALLOC TCB BR 80$ ; .ENDC 50$: MOV R1,R5 ;INIT POINTER TO START OF LIST 60$: MOV R5,R4 ;SAVE POINTER TO PREVIOUS MOV (R5),R5 ;POINT TO NEXT IN LIST BEQ 80$ ;IF EQ THERE IS NONE CMP 44(R5),-2(R3) ;MATCH ON FIRST WORD OF TASK NAME? BNE 60$ ;IF NE NO CMP 46(R5),(R3) ;MATCH ON SECOND WORD OF TASK NAME? BNE 60$ ;IF NE NO MOV (R5),(R4) ;UNLINK PACKET FROM LIST BNE 70$ ;IF NE IT WAS NOT THE LAST IN THE LIST MOV R4,2(R1) ;UPDATE LAST IN LIST POINTER 70$: CLR (R5) ;CLEAR LINK WORD MOV R5,@2(R0) ;LINK TO END OF ALLOCATED TCB LIST MOV R5,2(R0) ;UPDATE LAST IN LIST POINTER MOV R1,-(SP) ;SAVE T.RRFL PTR FOR PROTO TCB MOV R0,-(SP) ;SAVE T.RRFL PTR FOR CREATED TCB MOV 10(R5),R0 ;GET REGION ID TO SEARCH FOR ADD #A.TCBL,R0 ;ADJUST TO LINK WORD ADDR ADD #T.ATT-T.RRFL,R1 ;POINT TO PROTO ATT DESC LIST MOV R1,R2 ;MAKE A COPY OF LISTHEAD ADDRESS 72$: MOV R2,R4 ;SAVE POINTER TO LAST MOV (R2),R2 ;GET NEXT ADB BEQ 74$ ;IF EQ THERE IS NONE CMP R2,R0 ;THIS THE ONE ? BNE 72$ ;IF NE NO MOV (R2),(R4) ;UNLINK FROM LIST BNE 73$ ;IF NE NOT LAST IN LIST MOV R4,2(R1) ;UPDATE LAST IN LIST POINTER 73$: MOV (SP),R0 ;RESTORE POINTER TO CREATED T.RRFL ADD #T.ATT-T.RRFL,R0 ;POINT TO CREATED ATT DESC LIST MOV R2,@2(R0) ;INSERT IN SPAWNED ATT LIST MOV R2,2(R0) ;UPDATE LAST IN LIST MOV R0,A.TCB-A.TCBL(R2) ;CREATE POINTER IN A.TCB SUB #T.ATT,A.TCB-A.TCBL(R2) ;TO CORRECT TCB BICB #AS.PRO,A.STAT-A.TCBL(R2) ;INDICATE PRI. POOL TCB 74$: MOV (SP)+,R0 ;RESTORE REGISTERS MOV (SP)+,R1 ; BR 50$ ;RESTART SCAN 80$: CMP (R0)+,(R0)+ ;BUMP BOTH POINTERS CMP (R1)+,(R1)+ ; CALL @(SP)+ ;CALL THE CALLER BACK BR 40$ ; .ENDC ; DF R$$DSP ;+ ; **-$REMOV-REMOVE TASK ; **-$REMO1-REMOVE TASK DURING ERROR CLEANUP ; ; THIS ROUTINE IS STRICTLY DESIGNED TO REMOVE A TASK, WHICH HAS BEEN ; DYNAMICALLY INSTALLED BY THE EXECUTIVE-LEVEL DISPATCHING CODE, AS ; PART OF ERROR RECOVERY BEFORE THE TASK IS EVER ACTIVATED, OR A ; TASK BEING REMOVED ON TASK EXIT. IT WILL NOT, IN GENERAL, PROPERLY ; REMOVE ANY OTHER GIVEN TASK. ; ; $REMO1 IS AN ALTERNATE ENTRY TO BE USED WHEN CLEANING UP AFTER A ; FALSE START, SUCH AS WHEN THE SPAWN DIRECTIVE PASSES $TCBCP BUT ; FAILS TO START THE TASK. $REMO1 CHECKS THE UTILTITY LINK WORD TO ; SEE IF IT CONATINS THE KISAR6 BIAS OF THE PROTOTYPE TCB, AND SHOULD ; NOT BE CALLED IF THE TCB HAS BEEN CHANGED (E.G. FROM $DREIF) ; ; INPUTS: ; ; R0=TCB ADDRESS OF TASK TO BE REMOVED. ; ; OUTPUTS: ; ; NONE. ;- .ENABL LSB $REMO1:: ;REFERENCE LABEL .IF DF P$$OOL SAVNR ;SAVE NON-VOL. REGISTERS MOV KISAR6,-(SP) ;SAVE KERNEL MAPPING MOV (R0),KISAR6 ;MAP TO POSSIBLE SEC POOL TCB BEQ 5$ ;IF EQ TCB IN PRIMARY POOL MOV #140000,R1 ;POINT TO PROTOTYPE TCB CALL 15$ ;JOIN $REMOV BELOW MOV (SP)+,KISAR6 ;RESTORE PREVIOUS MAPPING RETURN ; 5$: MOV (SP)+,KISAR6 ;RESTORE PREVIOUS MAPPING BR 6$ ;SKIP SAVNR CALL IN $REMOV .ENDC ; DF P$$OOL $REMOV::SAVNR ;SAVE R4 AND R5 6$: ;REFERENCE LABEL CALL $DRCSR ;CANCEL ANY SCHEDULE REQUESTS MOV R5,R0 ;RESTORE TCB ADDRESS .IF DF P$$LAS CALL $CLSRF ;CLEAR ANY REC BY REF PKT PTRS TO TASK .ENDC MOV #$TSKHD-T.TCBL,R1 ;POINT TO START OF TASK LIST - T.TCBL CMP $TSKHD,R0 ;REMOVING FIRST IN LIST? BEQ 40$ ;IF EQ YES 10$: MOV T.TCBL(R1),R1 ;POINT TO NEXT IN LIST CMP T.TCBL(R1),R0 ;REMOVING NEXT IN LIST? BNE 10$ ;IF NE NO 15$: ;REFERENCE LABEL .IF DF P$$OOL MOV T.RCVL(R0),R2 ;ANY ENTRIES IN THE RECEIVE LIST? BEQ 30$ ;IF EQ NO MOV KISAR5,-(SP) ;SAVE KERNEL APR 5 MOV #120000,R4 ;POINT TO FIRST WORD OF PACKET MOV T.RCVL+2(R1),KISAR5 ;MAP THE LAST PACKET THROUGH APR 5 TST T.RCVL(R1) ;PROTO TCB RECEIVE LIST EMPTY? BNE 20$ ;IF NE NO MOV R1,R4 ;COPY PROTO TCB ADDRESS ADD #T.RCVL,R4 ;POINT TO RECEIVE LIST 20$: MOV R2,(R4) ;LINK RECEIVE ENTRIES TO PROTO LIST MOV T.RCVL+2(R0),T.RCVL+2(R1) ;FIX UP LAST IN LIST PTR MOV (SP)+,KISAR5 ;RESTORE KERNEL APR 5 .IFF MOV T.RCVL(R0),@T.RCVL+2(R1) ;LINK ENTRIES TO PROTO TCB BEQ 30$ ;IF EQ THERE ARE NONE MOV T.RCVL+2(R0),T.RCVL+2(R1) ;FIX UP LAST IN LIST PTR .ENDC 30$: ;REF LABEL .IF DF P$$LAS MOV T.RRFL(R0),@T.RRFL+2(R1) ;LINK ENTRIES TO PROTO TCB BEQ 40$ ;IF EQ THERE ARE NONE MOV T.RRFL+2(R0),T.RRFL+2(R1) ;FIX UP LAST IN LIST PTR .ENDC 40$: MOV T.ATT(R0),@T.ATT+2(R1) ;MOVE ADBS (FROM SREFS) BEQ 41$ ;IF EQ THERE WERE NONE MOV T.ATT(R0),T.ATT+2(R1) ;UPDATE LAST IN LIST POINTER MOV T.ATT(R0),R4 ;GET ADDRESS OF FIRST ADB IN LIST 412$: CMP #120000,R1 ;PROTOTYPE IN SECONDARY POOL ? BLOS 413$ ;IF LOS YES MOV R1,A.TCB-A.TCBL(R4) ;SET TCB ADDRESS BR 414$ ;FINISH LOOP IN COMMON 413$: BISB #AS.PRO,A.STAT-A.TCBL(R4) ;INDICATE SEC POOL TCB MOV KISAR6,A.TCB-A.TCBL(R4) ;AND FILL IN BIAS 414$: MOV (R4),R4 ;POINT TO NEXT ADB BNE 412$ ;IF NE THERE IS ONE 41$: MOV T.TCBL(R0),T.TCBL(R1) ;UNLINK TASK FROM TASK LIST MOV R0,R4 ;SAVE PCB ADDRESS MOV T.PCBV(R0),R0 ;POINT TO PCB VECTOR BEQ 50$ ;IF EQ THERE IS NONE MOV 2(R0),R1 ;POINT TO FIRST PCB IN VECTOR TST P.NAM(R1) ;NAMED PCB? BNE 45$ ;IF NE YES CMP P.OWN(R1),R4 ;IS THIS TCB USED FOR NAME? BNE 45$ ;IF NE NO MOV $TSKHD,R2 ;POINT TO FIRST INSTALLED TASK 43$: CMP T.PCBV(R2),R0 ;DOES THIS TASK USE THE PCBV VECTOR? BEQ 44$ ;IF EQ YES MOV T.TCBL(R2),R2 ;POINT TO NEXT INSTALLED TASK TST T.TCBL(R2) ;POINTING TO NULL TASK? BNE 43$ ;IF NE NO CLR R2 ;POINT P.OWN TO 0 FOR NOW 44$: MOV R2,P.OWN(R1) ;RESET P.OWN 45$: DECB 1(R0) ;REDUCE ACCESS COUNT IN VECTOR BNE 50$ ;IF NE THERE ARE STILL OTHERS INSTALLED MOV (R0),R1 ;ELSE PICK UP NUMBER OF PCB WORDS MOV 2(R0),R5 ;SAVE ADDRESS OF FIRST PCB INC R1 ;INCREMENT FOR FIRST WORD ASL R1 ;CONVERT TO BYTES TO DEALLOCATE CALL $DEACB ;DEALLOCATE PCB VECTOR MOV R5,R0 ;RESTORE ADDRESS OF FIRST PCB TST P.NAM(R0) ;RO SECTION OF MU TASK? BNE 50$ ;IF NE NO CALL $DELRG ;DELETE READ ONLY REGION 50$: MOV R4,R0 ;RESTORE TCB ADDRESS MOV #T.LGTH,R1 ;SET SIZE TO DEALLOCATE CALLR $DEACB ;DEALLOCATE TCB .DSABL LSB ;+ ; **-$CLSRF-CLEAR TASK TCB ADDRESS IN ALL RECEIVE BY REF PACKETS. ; ; THIS ROUTINE WILL SEARCH THE ACTIVE TASK LIST FOR TCBS WITH ; RECEIVE BY REFERENCE PACKETS WHICH CONTAIN A POINTER TO THE TASK ; BEING REMOVED. IF SUCH A POINTER IS FOUND IT IS CLEARED. ; ; INPUTS: ; ; R0=TCB ADDRESS OF TASK TO BE REMOVED. ; ; OUTPUTS: ; ; NONE. ; ;- $CLSRF:: ;REFERENCE SYMBOL .IF DF P$$LAS MOV $TSKHD,R1 ;GET FIRST TCB IN ATL 10$: TSTB T.SRCT(R0) ;ANY OUTSTANDING SREFS? BEQ 40$ ;IF EQ NO MOV T.TCBL(R1),-(SP) ;END OF LIST? BEQ 30$ ;IF EQ YES ADD #T.RRFL,R1 ;POINT TO RECEIVE BY REFERENCE LIST 20$: MOV (R1),R1 ;GET NEXT REC BY REF PACKET BEQ 30$ ;IF EQ END OF LIST CMP 2(R1),R0 ;DOES IT POINT TO TASK BEING REMOVED? BNE 20$ ;IF NE NO DECB T.SRCT(R0) ;DECREMENT OUTSTANDING SREF COUNT CLR 2(R1) ;CLEAR POINTER TO EXITTING TASK .IF DF G$$GEF MOV R0,-(SP) ;SAVE TCB OF EXITING TASK MOV R1,-(SP) ;SAVE PACKET ADDRESS MOV 6(R1),R3 ;GET EVENT FLAG MASK ADDRESS CALL $DEAGF ;DEACCESS IF GROUP GLOBAL MOV (SP)+,R1 ;RESTORE PACKET ADDRESS MOV (SP)+,R0 ;RESTORE TCB OF EXITING TASK .ENDC ; DF G$$GEF MOV T.NAM(R0),4(R1) ;STORE FIRST HALF OF TASK NAME MOV T.NAM+2(R0),6(R1) ;AND SECOND HALF BR 20$ ;GO AGAIN 30$: MOV (SP)+,R1 ;GET ADDRESS OF NEXT TCB IN LIST BNE 10$ ;IF NE GO AGAIN .IFTF 40$: RETURN ; .ENDC ;+ ; **-$DRTHR/$ERTHR-DIRECTIVE ERROR AND GENERAL ERROR THREADING ROUTINES ; ; THESE ROUTINES ARE USED IN CONJUNCTION WITH THE FOLLOWING ERROR ; RECOVERY ROUTINE TO DYNAMICALLY THREAD ERROR RECOVERY INFORMATION ; ONTO THE STACK. AFTER INITIALIZATION, THE INTERFACE IS VIA A ; COROUTINE CALL (CALL @(SP)+) FOLLOWED BY TWO ROUTINE ADDRESSES. ; THE FIRST ROUTINE IS CALLED AND THEN THE SECOND ROUTINE ADDRESS IS ; PUSHED ONTO THE STACK ALONG WITH THE CONTENTS OF R0 AND R1. IT IS ; INTENDED THAT THE SECOND ROUTINE, ALONG WITH THE SAVED CONTENTS OF ; R0 AND R1, CAN UNDO THE ACTION OF THE FIRST ROUTINE IF AN ERROR ; CONDITION IS ENCOUNTERED LATER. ANOTHER POSSIBILITY IS THAT THE FIRST ; ROUTINE IS NULL, AND THE SECOND ROUTINE CAN UNDO SOME PREVIOUS ACTION. ; $DRTHR MAY BE CALLED WHEN THE FINAL DESIRED ACTION ON ERROR WILL BE ; TO RETURN A DIRECTIVE STATUS PASSED IN R5 (IN THE FORM 'DRSTS D.RSX'). ; $ERTHR IS A GENERAL ERROR RECOVERY THREADING ROUTINE. EXAMPLE USES OF ; THESE ROUTINES MAY BE FOUND IN THE MODULE DRSPW. ; ; INPUTS: ; ; AS REQUIRED FOR CALL TO FIRST ROUTINE. ; ; OUTPUTS: ; ; C-BIT AND R0-R3 ARE PRESERVED FROM RETURN OF FIRST ROUTINE. ; R4 IS DESTROYED. ;- .IF DF P$$OFF .ENABL LSB $DRTHR::MOV (SP),R4 ;PICK UP RETURN PC MOV #10$,(SP) ;SET ADDRESS OF ROUTINE TO RETURN STATUS CMP -(SP),-(SP) ;ALLOCATE WORDS FOR R0 AND R1 MOV R4,-(SP) ;RESTORE RETURN PC ADDRESS .IF DF K$$DAS $ERTHR::MOV PS,R2 ;SAVE CURRENT PS WORD BIC #PMODE,PS ;SET PREVIOUS MODE TO KERNEL MOV (SP)+,R4 ;POP CALLING PC MFPI (R4)+ ;PUSH FIRST ROUTINE ADDRESS MFPI (R4)+ ;PUSH RECOVERY ROUTINE ADDRESS MOV R2,PS ;RESTORE PS WORD CALL @2(SP) ;CALL FIRST ROUTINE MOV (SP)+,(SP) ;MOVE RECOVERY ROUTINE ADDRESS INTO PLACE .IFF $ERTHR::MOV (SP),R4 ;PICK UP RETURN PC CALL @(R4)+ ;CALL THE FIRST ROUTINE ADDRESS MOV (R4)+,(SP) ;SAVE THE RECOVERY ROUTINE ADDRESS .ENDC MOV R1,-(SP) ;SAVE CURRENT CONTENTS OF R1 MOV R0,-(SP) ;SAVE CURRENT CONTENTS OF R0 CALL (R4) ;CALL THE CALLER BACK BR $ERTHR ;DO IT AGAIN 10$: MOV R5,-(SP) ;PUSH DIRECTIVE STATUS TRAP INSTRUCTION JMP (SP) ;EXECUTE TRAP .DSABL LSB ;+ ; **-$ERREC-ERROR RECOVERY ROUTINE ; ; THIS ROUTINE IS USED IN CONJUNCTION WITH THE ABOVE ROUTINES TO ; EFFECT A SERIES OF SUBROUTINE CALLS STORED ON THE STACK FOR ERROR ; RECOVERY. THE NORMAL CALLING SEQUENCE IS VIA A JUMP. SUCCESSIVE ; R0 AND R1 CONTENTS ARE POPPED FROM THE STACK WITH CALLS TO THE ; SAVED ROUTINE ADDRESSES. THE LAST ROUTINE ON THE STACK MUST FORCE ; THE PROCESS TO STOP. ; ; INPUTS: ; ; R5=DIRECTIVE STATUS (IF INITIALIZED BY $DRTHR). ; ; OUTPUTS: ; ; NONE. ;- $ERREC::TST (SP)+ ;POP COROUTINE ADDRESS 10$: MOV (SP)+,R0 ;PICK UP SAVED R0 MOV (SP)+,R1 ;PICK UP SAVED R1 CALL @(SP)+ ;CALL THE RECOVERY ROUTINE BR 10$ ; ;+ ; **-$QUEXT-QUEUE EXIT "AST" BLOCK ; ; THIS ROUTINE FILLS IN THE STATUS IN AN OFFSPRING CONTROL BLOCK, ; AND QUEUES IT AS A SPECIAL AST BLOCK TO THE PARENT TASK TCB. ; ; INPUTS: ; ; R0=EXIT STATUS WORD. ; R1=OCB ADDRESS. ; R2=TKTN ABORT CODE (BYTE) ; ; OUTPUTS: ; ; R3 IS PRESERVED. ;- .IFTF $QUEXT:: ;UNCONDITIONALLY DEFINE FOR MCR .IFT MOV R2,-(SP) ;SAVE ABORT CODE .IF DF N$$DIR ;IF NAMED DIRECTORY SUPPORT MOV R1,-(SP) ;SAVE OCB ADDRESS MOV O.STAT+10(R1),R1 ;GET CONTEXT BLOCK POINTER BEQ 5$ ;IF EQ, NONE CALL $DLCTX ;DELETE CONTEXT BLOCK 5$: MOV (SP)+,R1 ;RESTORE OCB POINTER .ENDC ;DF N$$DIR MOV O.PTCB(R1),R2 ;PICK UP PARENT TCB ADDRESS BEQ 30$ ;IF EQ PARENT HAS EXITTED DEC T.RDCT(R2) ;DECREMENT RUNDOWN COUNT MOV T.ASTL(R2),(R1) ;LINK OCB TO FRONT OF AST LIST BNE 10$ ; MOV R1,T.ASTL+2(R2) ; 10$: MOV R1,T.ASTL(R2) ; MOV #AK.OCB,A.CBL(R1) ;SET EXIT "AST" BLOCK FLAG MOV R0,O.STAT(R1) ;SET EXIT STATUS MOV (SP)+,O.STAT+2(R1) ;PUT ABORT CODE IN OCB MOV R2,R0 ;COPY PARENT TCB POINTER ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 09. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH09==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL CALL @#$SETCR ;SET CONDITIONAL SCHEDULE REQUEST MOV T.PCB(R0),R0 ;POINT TO PARENT PCB CALLR $NXTSK ;REALLOCATE (AST ENTRY CAN UNSTOP) 30$: MOV R1,R0 ;COPY OCB POINTER TO DEALLOCATE TST (SP)+ ;CLEAN STACK (ABORT CODE) MOV #O.LGTH,R1 ;SET LENGTH TO DEALLOCATE CALLR $DEACB ;DEALLOCATE OCB .ENDC ;+ ; **-$STPCT-STOP CURRENT TASK ; **-$STPTK-STOP TASK ; ; THESE ROUTINES ARE CALLED TO STOP A TASK AND REALLOCATE THE TASK'S ; PARTITION. ; ; INPUTS: ; ; R0=TCB ADDRESS OF TASK TO STOP (IF ENTRY AT $STPTK) ; ; OUTPUTS: ; ; NONE ;- $STPCT::MOV $TKTCB,R0 ;PICK UP ADDRESS OF CURRENT TASK TCB $STPTK::BIS #T2.STP,T.ST2(R0) ;SET STOP BIT IN TASK'S TCB .IF DF M$$PRO BIT #TS.RUN,T.STAT(R0) ;TASK RUNNING ON SOME PROCESSOR? BEQ 10$ ;IF EQ NO .IFF CMP R0,$TKTCB ;TASK RUNNING? BNE 10$ ;IF NE NO .ENDC CALL $SETCR ;INSURE THAT TASK WILL STOP 10$: MOV T.PCB(R0),R0 ;POINT TO TASK PCB BR $NXTSK ;REALLOCATE TASK PARTITION ;+ ; **-$RLCPS-RELEASE CHECKPOINT SPACE ; ; THIS ROUTINE RELEASES SPACE IN A CHECKPOINT FILE. IF THE SPECIFIED ; REGION IS TO BE DELETED, IT ALSO DELETES ANY DISK PCB AND THE ; REGION PCB ITSELF. ; ; INPUTS: ; ; R0=REGION PCB FOR WHICH SPACE IS TO BE DELETED. ; ; OUTPUTS: ; ; NONE. ;- $RLCPS::SAVNR ;SAVE R4 AND R5 MOV R0,R4 ;COPY PCB POINTER MOV P.DPCB(R4),R1 ;POINT TO REGION DISK PCB BEQ 25$ ;IF EQ THERE IS NONE CMP R1,P.MAIN(R1) ;IS THIS A CHECKPOINT PCB? BEQ 25$ ;IF EQ NO CALL $RLPR1 ;RELEASE THE CHECKPOINT SPACE MOV R4,-(SP) ;SAVE PCB ADDRESS MOV P.DPCB(R4),R4 ;POINT TO CHECKPOINT ALLOCATION PCB MOV P.MAIN(R4),R4 ;POINT TO CHECKPOINT FILE PCB TST P.REL(R4) ;CHECKPOINT FILE STILL IN USE? BEQ 10$ ;IF EQ YES TST P.SUB(R4) ;CHECKPOINT FILE EMPTY? BNE 10$ ;IF NE NO MOV #20,R0 ;SET TKTN CODE MOV P.UCB(R4),R5 ;PASS UCB ADDRESS CALL $DVMSG ;QUEUE MESSAGE TO TKTN 10$: MOV (SP)+,R4 ;RESTORE REGION PCB ADDRESS MOV P.DPCB(R4),R0 ;POINT TO DISK PCB 20$: CLR P.DPCB(R4) ;CLEAR OUT DISK PCB POINTER MOV #P.DLGH,R1 ;SET LENGTH TO DEALLOCATE CALL $DEACB ;DEALLOCATE DISK PCB 25$: BIT #PS.DEL,P.STAT(R4) ;IS REGION MARKED FOR DELETE? BEQ 30$ ;IF EQ NO TST P.ATT(R4) ;ANYONE STILL ATTACHED? BNE 30$ ;IF NE YES MOV P.DPCB(R4),R0 ;POINT TO DISK PCB BNE 20$ ;IF NE THERE IS ONE MOV R4,R0 ;COPY MAIN PCB POINTER TO DEALLOCATE MOV #P.LGTH,R1 ;SET LENGTH TO DEALLOCATE CALL $DEACB ;DEALLOCATE PCB 30$: RETURN ; ;+ ; **-$RLPAR-RELEASE TASK PARTITION ; **-$RLPR1-RELEASE PARTITION ; ; THIS ROUTINE IS CALLED TO RELEASE SPACE IN A PARTITION OWNED BY A TASK ; AND TO ATTEMPT TO REALLOCATE THE PARTITION IF THE WAIT QUEUE FOR ; THE PARTITION IS NONEMPTY. ; ; INPUTS: ; ; R0=ADDRESS OF THE TCB OF THE OWNER TASK (IF ENTRY AT $RLPAR) ; R1=ADDR OF SUBPARTITION PCB TO RELEASE (IF ENTRY AT $RLPR1) ; ; OUTPUTS: ; ; THE SPACE IS RELEASED AND AN ATTEMPT IS MADE TO REASSIGN SPACE ; IN THE PARTITION TO THE NEXT HIGHEST PRIORITY CONTENDER(S). ;- $RLPAR::MOV T.PCB(R0),R1 ;GET ADDRESS OF PARTITION PCB $RLPR1::MOV P.MAIN(R1),R0 ;GET MAIN PCB ADDRESS MOV R0,R3 ;SAVE POINTER TO MAIN PCB 10$: MOV R0,R2 ;SAVE ADDRESS OF PREVIOUS PCB MOV P.SUB(R2),R0 ;GET ADDRESS OF NEXT PCB CMP R0,R1 ;TASK PCB? BNE 10$ ;IF NE NO MOV P.SUB(R0),P.SUB(R2) ;REMOVE PCB FROM LIST TST P.MAIN(R3) ;RELEASING CHECKPOINT SPACE? BNE 20$ ;IF NE NO RETURN 20$: ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 15. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH15==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL NOP ;DROP THROUGH TO $NXTSK TO NOP ; REALLOCATE RELEASED PARTITION ;+ ; **-$NXTSK-ASSIGN NEXT TASK TO PARTITION ; ; THIS ROUTINE IS CALLED TO ASSIGN SPACE IN A PARTITION TO THE HIGHEST ; PRIORITY CONTENDERS WAITING TO OCCUPY THE PARTITION. ; ; INPUTS: ; ; R0=ADDRESS OF THE PCB OF THE MAIN PARTITION, OR A SUBPARTITION ; PCB WITHIN THE MAIN PARTITION IN WHICH TO ASSIGN SPACE. ; ; OUTPUTS: ; ; THIS ROUTINE ATTEMPTS TO ASSIGN SPACE IN THE MAIN PARTITION IN ; AS MANY AS FOUR STEPS AS FOLLOWS: ; ; 1. IT FIRST DETERMINES IF THERE ARE ANY ELIGIBLE CONTENDERS ; IN THE PARTITION WAIT QUEUE. THE ONLY CONTENDERS WHICH ; CAN BE IN THE WAIT QUEUE WHICH ARE NOT ELIGIBLE ARE TASK ; PARTITIONS WHICH ARE NOT MAPPED BY OTHER RESIDENT TASKS ; AND FOR WHICH THE CORRESPONDING TASK IS STOPPED WITH NO ; PENDING AST QUEUE ENTRIES. ; ; 2. IF THERE IS AN ELIGIBLE CONTENDER FOR MEMORY, THE ; ROUTINE ATTEMPTS TO ASSIGN SPACE TO THE CONTENDER FROM ; SPACE WHICH IS CURRENTLY FREE. ; ; 3. IF THERE IS CURRENTLY INSUFFICIENT FREE SPACE TO BRING ; IN THE CONTENDER, AN ATTEMPT IS MADE TO CREATE A ; CONTIGUOUS FREE SPACE LARGE ENOUGH BY CHECKPOINTING ; ONE OR MORE OF THE CURRENT RESIDENTS OF THE PARTITION. ; (NOTE THAT DURING THIS STEP THE DECISION MAY BE MADE TO ; CHECKPOINT A REGION FOR WHICH CHECKPOINTING HAS ALREADY ; BEEN INITIATED. THIS IS ACCEPTABLE SINCE AN ATTEMPT TO ; INITIATE CHECKPOINTING A SECOND TIME IS EFFECTIVELY A ; NOP.) ; ; 4. IF SUFFICIENT SPACE CANNOT BE CREATED BY CHECKPOINTING, ; THE SHUFFLER IS ACTIVATED. ;- $NXTSK:: .IF DF R$$PRO!A$$CKP TST $NXTLK ;NXTSK LOCK SET? (NEEDED TO MAINTAIN CONTEXT ;DURING CHECKPOINTS) BLE 5$ ;IF LE NO, OK TO ENTER RETURN ;LEAVE NOW 5$: .ENDC ;R$$PRO!A$$CKP SAVNR ;SAVE R4 AND R5 MOV P.MAIN(R0),R5 ;GET MAIN PARTITION PCB ADDRESS 10$: MOV P.WAIT(R5),R4 ;GET FIRST PCB IN WAIT LIST 20$: BEQ 100$ ;IF EQ END OF LIST TSTB P.RMCT(R4) ;ARE THERE ANY RESIDENT MAPPED TASKS? BNE 40$ ;IF NE YES, ATTEMPT TO BRING IN MOV P.TCB(R4),R0 ;GET TCB ADDR (TASK PART. IF P.RMCT=0) BIT #TS.STP,T.STAT(R0) ;TASK BLOCKED BY BLOCK COMMAND BNE 30$ ;IF NE YES, SKIP IT BIT #T2.STP,T.ST2(R0) ;TASK STOPPED? BEQ 40$ ;IF EQ NO TST T.ASTL(R0) ;BUT ARE THERE PENDING ASTS? BNE 40$ ;IF NE YES 30$: MOV (R4),R4 ;POINT TO NEXT PCB IN WAIT LIST BR 20$ ;GO AGAIN 40$: BIT #PS.CSA,P.STAT(R4) ;CHECKPOINT SPACE ALLOCATED? BNE 100$ ;IF NE, YES - JUST RETURN CALL $FNDSP ;ATTEMPT TO ALLOCATE SPACE IN MAIN PART. BCS 50$ ;IF CS NO SPACE CURRENTLY AVAILABLE MOV R5,R0 ;COPY MAIN PCB ADDRESS ADD #P.WAIT,R0 ;POINT TO WAIT QUEUE LISTHEAD MOV R4,R1 ;COPY ADDRESS OF PCB TO REMOVE .IF DF R$$PRO MOV P.REL(R4),$NXTBA ;SET BASE TO BIAS ADD P.SIZE(R4),$NXTBA ;FOLLOWING LAST SUCCESSFUL ALLOCATION .ENDC .IF DF A$$CKP MOV P.REL(R4),P.NXBA(R5) ; SET THE NEXT BASE ADDRESS FOR PCB ADD P.SIZE(R4),P.NXBA(R5) ; UPDATE THE INFORMATION .ENDC ;DF,A$$CKP CALL $QRMVA ;REMOVE PCB FROM WAIT QUEUE CALL $LOADT ;PLACE IT IN LOADER QUEUE TALLY$ B.RLOD,XA$$TL ;COUNT A REGION LOAD BR 10$ ;TRY TO LOAD ANOTHER ; ; ATTEMPT TO CREATE A CONTIGUOUS FREE SPACE LARGE ENOUGH BY CHECKPOINTING ; ONE OR MORE TASKS/COMMONS. ON P/OS, START LOOKING FOR THIS CONTIGUOUS ; FREE SPACE FOLLOWING THE LAST SUCCESSFUL LOAD. THIS AVOIDS THE THRASHING ; STATE WHEREBY A TASK IS MAPPING AND UNMAPPING FROM VARIOUS CLUSTERED ; LIBRARIES WHICH CHECKPOINT EACH OTHER AS A CONSEQUENCE OF HAVING NO FREE ; SPACE DUE TO A RESIDENT UNMAPPED COMMON(S) HIGHER IN GEN. ; 50$: .IF DF R$$PRO!A$$CKP TST $NXTLK ;JUST STARTING TO LOOK? BGT 53$ ;IF NE NO, WRAP BACK TO BOTTOM OF PARTITION BMI 54$ ; IF MI, USING RSX STYLE CHECKPOINT INCB $NXTLK ;LOCK $NXTSK TO PREVENT LOSS OF CONTEXT ;VIA RECURSIVE CALL OUT OF $ICHKP .IF DF A$$CKP MOV R5,R2 ; COPY MAIN PCB ADDRESS TO R2 .ENDC ;DF,A$$CKP MOV P.SUB(R5),R1 ;GET FIRST SUBPARTITION MOV R1,R5 ;SET UP PREVIOUS 52$: .IF DF A$$CKP CMP P.REL(R1),P.NXBA(R2) ; ABOVE LAST SUCCESSFUL LOAD? .IFF ;DF,A$$CKP CMP P.REL(R1),$NXTBA ;ABOVE LAST SUCCESSFUL LOAD? .ENDC ;DF,A$$CKP BHIS 65$ ;IF HIS YES MOV R1,R5 ;UPDATE PREVIOUS MOV P.SUB(R1),R1 ;POINT TO NEXT SUBPARTITION BNE 52$ ;TRY AGIAN 53$: INCB $NXTLK ;INDICATE FULL BOTTOM TO TOP PASS MOV P.MAIN(R4),R5 ;SET UP POINTER TO MAIN PCB 54$: .ENDC ;R$$PRO!A$$CKP CLR R3 ;INIT BASE OF HOLE REGISTER MOV R5,R1 ;COPY MAIN PCB PTR LEAVING PTR TO PREV 55$: ADD P.REL(R5),R3 ;CALCULATE BASE OF HOLE 60$: MOV P.SUB(R1),R1 ;POINT TO NEXT SUBPARTITION PCB BEQ 110$ ;IF EQ NONE, FAILED TO CHECKPOINT 65$: CALL $TSTCP ;CAN WAITING PCB CHECKPOINT? BCC 70$ ;IF CC YES MOV R1,R5 ;UPDATE POINTER TO PREVIOUS PCB MOV P.SIZE(R5),R3 ;INIT BASE OF HOLE REGISTER BR 55$ ;TRY AGAIN 70$: CLR R0 ;INITIALIZE SIZE OF HOLE MOV P.SUB(R1),R2 ;POINT TO NEXT PCB AFTER HOLE BNE 80$ ;IF NE THERE IS ONE MOV P.MAIN(R1),R2 ;ELSE POINT TO MAIN PCB ADD P.SIZE(R2),R0 ;CALCULATE END OF PARTITION 80$: ADD P.REL(R2),R0 ;CALCULATE ADDRESS OF TOP OF HOLE SUB R3,R0 ;CALCULATE SIZE OF HOLE CMP R0,P.SIZE(R4) ;IS THE HOLE BIG ENOUGH? BLO 60$ ;IF LO NO BIS #PS.CSA,P.STAT(R4) ;INDICATE CHECKPOINT SPACE ALLOCATED MOV R4,-(SP) ;SAVE PCB IN WAIT QUEUE MOV R1,R4 ;MARK LAST PCB TO CHECKPOINT 90$: MOV P.SUB(R5),R5 ;POINT TO NEXT PCB TO CHECKPOINT MOV R5,R1 ;COPY ITS ADDRESS CALL $ICHKP ;INITIATE CHECKPOINT CMP R5,R4 ;MORE TO CHECKPOINT? BNE 90$ ;IF NE YES MOV (SP)+,R4 ;RESTORE PCB OF WAITING TASK BIC #PS.CSA,P.STAT(R4) ;INDICATE CHECKPOINT IS DONE 100$: .IF DF R$$PRO!A$$CKP CLRB $NXTLK ;CLEAR $NXTSK LOCK .ENDC ;R$$PRO!A$$CKP RETURN ; 110$: .IF DF R$$PRO!A$$CKP CMP $NXTLK,#1 ;WRAP BACK TO BEGINNING OF PARTITION? .IF NDF R$$PRO BEQ 53$ ; IF EQ, YES, SCAN ONCE MORE CLRB $NXTLK ; REMOVE OUR LOCK TO ALLOW RE-ENTRY .IFF ;NDF,R$$PRO BNE 100$ ;IF NE NO BR 53$ ; .ENDC ;NDF,R$$PRO .ENDC ;DF,R$$PRO!A$$CKP MOV $SHFPT,R0 ;PICK UP ADDRESS OF SHUFFLER TCB BEQ 100$ ;IF EQ SHUFFLER NOT INSTALLED TST $SHFTM ;CAN WE REQUEST THE SHUFFER ? BNE 100$ ;NO, WAIT FOR NEXT TIME INTERVAL BIT #TS.EXE,T.STAT(R0) ;YES, SHUFFLER ALREADY ACTIVE ? BEQ 100$ ;IF EQ, YES, EXIT .IF DF A$$CNT MOV KISAR6,-(SP) ;SAVE CURRENT MAPPING MOV $SABPT,KISAR6 ;MAP SAB BEQ 130$ ;IF EQ, ACCOUNTING NOT ACTIVE BIT #BF.LSS,$ACNFE ;SYSTEM ACCOUNTING TURNED ON ? BEQ 130$ ;NO, IF EQ. ADD #1,@#B.SHF+140002 ;COUNT SHUFFLER STARTUP ADC @#B.SHF+140000 ; 130$: MOV (SP)+,KISAR6 ;RESTORE MAPPING .ENDC CALLR $EXRQN ;REQUEST THE SHUFFLER AND RETURN ;+ ;**-$TSPAR-TEST IF PARTITION IS IN MEMORY FOR KERNEL AST ; ; THIS ROUTINE IS CALLED TO CHECK A REGION FOR MEMEORY RESIDENCE ; TO DETERMINE IF IT IS SAFE TO SERVICE A KERNEL AST (E.G. COPY ; A BUFFER) INTO THE REGION. IF THE REGION IS CHECKPOINTED OR ; CURRENTLY BEING CHECKPOINTED, THEN A REGION LOAD AST IS QUEUED ; AND THE REGION IS ACCESSED ON THE TASKS BEHALF. ; ; INPUTS: ; R0=ADDRESS OF PACKET PEING PROCESSED ; R1=PCB ADDRESS OF REGION ; R5=TCB ADDRESS OF ASSOCIATED TASK ; ; OUTPUTS: ; C=0 IF REGION IS MEMORY RESIDENT ; C=1 IF REGION IS NON-RESIDENT. IN THIS CASE THE REGION AST ; HAS BEEN QUEUED, ETC. ;- $TSPAR::CLC ;ASSUME REGION IS IN MEMORY BIT #PS.CKP!PS.OUT,P.STAT(R1) ;REGION IN MEMORY ? BNE 10$ ;IF NE NO RETURN ; 10$: BIT #PS.AST,P.STAT(R1) ;ALREADY A LOAD AST ? BNE 20$ ;IF NE YES BIS #PS.AST,P.STAT(R1) ;INDICATE LOAD AST QUEUED CLR P.SWSZ(R1) ;USE P.SWSZ FOR A LISTHEAD 20$: MOV P.SWSZ(R1),(R0) ;LINK NEXT BLOCK TO THIS ONE MOV R0,P.SWSZ(R1) ;AND SET THIS ONE FIRST IN LIST MOV R0,-(SP) ;SAVE TCB ADDRESS MOV R5,R0 ;COPY TCB ADDRESS CALL $ACCRG ;ACCESS THE REGION MOV (SP)+,R0 ;RESTORE PACKET ADDRESS SEC ;INDICATE AST QUEUED RETURN ; ;+ ; **-$ACCRG-ACCESS REGION ; **-$ALTRG-ALTER REGION PRIORITY ; ; EFFECT THE ACCESS OF A NEW RESIDENT MAPPED TASK TO A REGION AND ; OPTIONALLY ALTER THE PRIORITY OF THE REGION. ; ; INPUTS: ; ; R0=TCB ADDRESS OF RESIDENT MAPPED TASK. ; R1=PCB ADDRESS OF REGION. ; ; OUTPUTS: ; ; NONE. ;- .ENABL LSB $ACCRG::MOV T.PCB(R0),R2 ;PICK UP TASK REGION PCB PTR CMP R1,R2 ;ACCESSING TASK REGION? BEQ 4$ ;IF EQ YES, DON'T INCREMENT P.RMCT .IF DF M$$PRO BIS P.RRM(R1),T.RRM(R0) ;INCLUDE REGION AFFINITY IN TASK AFF .ENDC BIT #PS.OUT,P.STAT(R2) ;TASK OUT OF MEMORY ? BNE 3$ ;IF NE YES, OK TO INC P.RMCT BIT #PS.CKP,P.STAT(R2) ;BEING CHECKPOINTED ? BNE 43$ ;IF NE YES, DON'T TOUCH P.RMCT 3$: INCB P.RMCT(R1) ;INC RESIDENT MAPPED TASK COUNT 4$: BIT #PS.CKP,P.STAT(R2) ;IS THIS A CHECKPOINT READ ACCESS? BNE $ALTRG ;IF NE YES, SKIP BLOCKING CHECKS 43$: ;REFERENCE LABEL BIT #PS.OUT!PS.CKP,P.STAT(R1) ;IS REGION IN MEMORY? BEQ 5$ ;IF EQ YES INC T.STAT(R0) ;BLOCK MAPPING TASK BR 6$ ; 5$: BIT #PS.CKR,P.STAT(R1) ;IS THERE A CHECKPOINT REQUEST? BEQ 6$ ;IF EQ NO BIS #TS.CIP,T.STAT(R0) ;BLOCK MAPPING TASK 6$: MOV R1,R2 ;SAVE PCB ADDRESS .IF DF M$$PRO BIT #TS.RUN,T.STAT(R0) ;IS THE TASK RUNNING ON SOME PROC? BEQ 7$ ;NO IF EQ .IFF CMP R0,$TKTCB ;IS THIS THE CURRENT TASK? BNE 7$ ;NO IF NE .ENDC CALL $SETCR ;SET SCHEDULE REQUEST TO STOP TASK 7$: MOV R2,R1 ;RESTORE PCB ADDRESS $ALTRG::MOVB T.PRI(R0),R2 ;PICK UP TASK PRIORITY CMP R1,T.PCB(R0) ;ALTERING TASKS OWN REGION? BNE 10$ ;IF NE NO TSTB P.RMCT(R1) ;OTHER TASKS MAPPED TO TASK REGION? BEQ 15$ ;IF EQ NO ; ; THIS SECTION INSURES THAT THE PRIORITY OF A NON-RESIDENT ; NON-MAPPED REGION STAYS AT ZERO WHEN ALTERED. THIS IS ; NECESSARY TO INSURE THAT ZERO MAP COUNT COMMONS DON'T GET ; PUT IN THE PAR. WAIT QUEUE, AND TO INSURE THAT THE REGION ; WILL GET LOADED WHEN IT IS MAPPED BY SOME TASKS. NOTE THAT ; IF THE PRIORITY IS NOT ALTERED UPWARD, THE REGION IS NOT ; LOADED. ALSO NOTE THAT THE NEXT TEST WILL NEVER BRANCH FOR ; TASK REGIONS, SINCE WE JUST CHECKED P.RMCT ABOVE. ; 10$: TSTB P.RMCT(R1) ;ANY TASK MAPPED TO THIS REGION ? BEQ 30$ ;IF EQ NO - DON'T TOUCH PRIORITY INCB R2 ;INCREMENT FOR COMMON PRIORITY CMPB R2,P.PRI(R1) ;IS NEW PRIORITY HIGHER? BLOS 30$ ;IF LOS NO 15$: MOVB R2,P.PRI(R1) ;STORE NEW REGION PRIORITY $LDREG::BIT #PS.OUT,P.STAT(R1) ;IS THE REGION IN MEMORY? BEQ 30$ ;IF EQ YES CMP R1,$LDPCB ;IS LOADER CURRENTLY LOADING IT? BEQ 30$ ;IF EQ YES MOV $LDRPT,R0 ;POINT TO LOADER TCB ADD #T.RCVL,R0 ;POINT TO LOADER'S RECEIVE QUEUE CALL $QRMVA ;SEE IF PCB IS IN LOADER QUEUE BCS 20$ ;IF CS NO CALL $QINSP ;ELSE PUT IT BACK BR 30$ ; 20$: ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 06. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH06==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL MOV P.MAIN(R1),R0 ;POINT TO MAIN PCB ADD #P.WAIT,R0 ;POINT TO WAIT QUEUE LISTHEAD CALL $QRMVA ;REMOVE FROM CURRENT POSITION (IF THERE) CALL $QINSP ;INSERT IN PARTITION WAIT QUEUE 25$: MOV R1,R0 ;SET PCB ADDRESS FOR $NXTSK CALL $NXTSK ;REALLOCATE MAIN PARTITION 30$: RETURN ; ;+ ; **-$DEARG-DEACCESS REGION ; ; THIS ROUTINE DEACCESSES A MAPPED TASK FROM A REGION AND REALLOCATES ; ITS MAIN PARTITION IF THE REGION HAS NO MORE MAPPED TASKS. ; ; INPUTS: ; ; R0=TCB ADDRESS OF DEACCESSING TASK ; R1=PCB OF REGION TO DEACESS ; ; OUTPUTS: ; ; NONE. ;- $DEARG::TSTB T.IOC(R0) ;DOES TASK HAVE OUTSTANDING I/O? BEQ 35$ ;IF EQ NO BIS #T3.MPC,T.ST3(R0) ;SET MAPPING CHANGE BIT 35$: BIT #PS.CKR,P.STAT(R1) ;CHECKPOINT REQUEST THIS REGION? BEQ 40$ ;IF EQ NO BIC #PS.CKR,P.STAT(R1) ;CLEAR CHECKPOINT REQUEST BIT MOV R1,-(SP) ;SAVE REGISTERS MOV R0,-(SP) ; CALL $ICHKP ;ATTEMPT TO INITIATE CHECKPOINT MOV (SP)+,R0 ;RESTORE REGISTERS MOV (SP)+,R1 ; 40$: CMP R1,T.PCB(R0) ;TASK REGION? BNE 45$ ;NO IF NE TST @P.ATT(R1) ;OTHER ATTACHES TO TASK'S REGION? BEQ 30$ ;IF EQ NO, SAVE SOME TIME INCB P.RMCT(R1) ;INSURE NO MODIFICATION OF P.RMCT 45$: DECB P.RMCT(R1) ;DEC COUNT OF RESIDENT MAPPED TASKS BNE 30$ ;IF NE THERE ARE STILL OTHERS CLRB P.PRI(R1) ;ASSUME IT IS A COMMON BIT #PS.COM,P.STAT(R1) ;IS IT A COMMON? BEQ 47$ ;IF EQ NO BIT #PS.OUT,P.STAT(R1) ;REGION OUT OF MEMEORY ? BEQ 50$ ; IF EQ NO - REALLOCATE PARTITION MOV R0,-(SP) ;SAVE TCB ADDRESS OF TASK MOV R1,-(SP) ;SAVE PCB ADDRESS OF REGION MOV P.MAIN(R1),R0 ;POINT TO REGION MAIN PARTITION ADD #P.WAIT,R0 ;POINT TO WAIT QUEUE LISTHEAD CALL $QRMVA ;REMOVE FROM QUEUE IF THERE MOV (SP)+,R1 ;RESTORE PCB ADDRESS MOV (SP)+,R0 ;AND TCB ADDRESS BCS 46$ ;IF CS WASN'T IN WAIT QUEUE BIC #PS.CKR,P.STAT(R1) ;CLEAR CHECKPOINT REQUEST 46$: RETURN ; 47$: MOV P.TCB(R1),R0 ;POINT TO TASK TCB MOVB T.PRI(R0),P.PRI(R1) ;THEN SET TO TASK PRIORITY 50$: MOV R1,R0 ;COPY PCB ADDRESS CALLR $NXTSK ;REALLOCATE MAIN PARTITION AND RETURN .DSABL LSB ;+ ; **-$FNDSP-FIND SPACE IN PCB LIST ; ; THIS ROUTINE IS CALLED TO FIND SPACE WITHIN A DYNAMICALLY ALLOCATED ; PCB LIST REPRESENTING THE ALLOCATION STATE OF A SYSTEM CONTROLLED ; PARTITION OR DYNAMIC CHECKPOINT FILE. ; ; INPUTS: ; ; R4=ADDRESS OF PCB TO FIND SPACE FOR ; R5=ADDRESS OF MAIN PCB FOR SPACE IN WHICH TO ALLOCATE ; ; OUTPUTS: ; ; C=0 IF ALLOCATION WAS SUCCESSFUL ; SUB PCB IS LINKED INTO ALLOCATION LIST ; C=1 IF ALLOCATION FAILURE ; ; R0,R1,R2 ARE MODIFIED. ;- $FNDSP::MOV R5,R0 ;COPY ADDRESS OF MAIN PCB MOV P.REL(R5),R2 ;SET HIGHEST ADDRESS IN LAST PARTITION 10$: MOV P.SUB(R0),R1 ;GET ADDRESS OF NEXT PCB BEQ 20$ ;IF EQ END OF LIST MOV P.REL(R1),-(SP) ;CALCULATE SIZE OF HOLE SUB R2,(SP) ; CMP (SP)+,P.SIZE(R4) ;HOLE BIG ENOUGH? BHIS 30$ ;IF HIS YES MOV R1,R0 ;SAVE ADDRESS OF PREVIOUS PCB MOV P.REL(R1),R2 ;CALCULATE BASE ADDRESS OF NEXT HOLE ADD P.SIZE(R1),R2 ; BR 10$ ; 20$: MOV P.REL(R5),-(SP) ;CALCULATE SIZE OF LAST HOLE ADD P.SIZE(R5),(SP) ; SUB R2,(SP) ; CMP (SP)+,P.SIZE(R4) ;HOLE BIG ENOUGH? BLO 40$ ;IF LO NO 30$: MOV R2,P.REL(R4) ;SET ADDRESS OF TASK PARTITION MOV R4,P.SUB(R0) ;LINK ALLOCATED PARTITION TO PREVIOUS MOV R1,P.SUB(R4) ;LINK NEXT TO TASK PCB 40$: RETURN ; ;+ ; **-$TSTCP-TEST IF CHECKPOINT SHOULD BE INITIATED ; ; INPUTS: ; ; R1=ADDRESS OF RESIDENT PCB ; R4=ADDRESS OF CONTENDING PCB ; ; OUTPUTS: ; ; C=0 IF CHECKPOINT SHOULD BE INITIATED. ; C=1 IF CHECKPOINT SHOULD NOT BE INITIATED. ; ; R1,R3,R4 AND R5 ARE PRESERVED. ;- $TSTCP::BIT #PS.CHK!PS.FXD,P.STAT(R1) ;IS PCB CHECKPOINTABLE? BNE 30$ ;IF NE NO TSTB P.RMCT(R1) ;BUT ARE THERE RESIDENT MAPPED TASKS? BNE 30$ ;IF NE YES, CANNOT CHECKPOINT BIT #PS.COM,P.STAT(R1) ;IS IT AN UNMAPPED COMMON REGION? BNE 40$ ;IF NE YES, IT CAN GO MOV P.TCB(R1),R2 ;AT THIS POINT MUST BE A TASK, GET TCB BIT #T2.HLT,T.ST2(R2) ;IS TASK EXITING? BNE 30$ ;IF NE YES, CANNOT CHECKPOINT BIT #T2.STP,T.ST2(R2) ;IS THE TASK STOPPED? BEQ 10$ ;IF EQ NO TST T.ASTL(R2) ;BUT DOES IT HAVE PENDING AST? BEQ 40$ ;IF EQ NO, IT CAN GO 10$: BIT #TS.STP,T.STAT(R2) ;BLOCKED BY MCR BLOCK CMD ? BNE 40$ ;IF NE YES, IT CAN GO .IF DF S$$WPC MOV $SWPR,R0 ;ASSUME TASK NOT IN MEMORY BIT #PS.CKP!PS.CKR!PS.OUT,P.STAT(R1) ;TASK IN MEMORY? BNE 15$ ;IF NE NO .IF DF X$$HDR MOV KISAR6,-(SP) ;SAVE CURRENT MAPPING FOR XTRNL HDR MOV P.HDR(R1),R0 ;SAVE HEADER POINTER BNE 12$ ;IF NE INTERNAL HEADER MOV P.REL(R1),KISAR6 ;MAP TO EXTERNAL HEADER MOV #140000,R0 ;RESET VIRTUAL ADDRESS OF HEADER 12$: ;REFERENCE LABEL .IFF ; DF X$$HDR MOV P.HDR(R1),R0 ;GET ADDRESS OF TASK HEADER .ENDC ; DF X$$HDR MOVB H.SPRI(R0),R0 ;PICK UP CURRENT SWAPPING PRIORITY .IF DF X$$HDR MOV (SP)+,KISAR6 ;RESTORE PREVIOUS EXEC MAPPING .ENDC ; DF X$$HDR 15$: CLR -(SP) ;EXTRACT TASK PRIORITY AS WORD BISB T.PRI(R2),(SP) ; ADD (SP)+,R0 ;ADD TASK PRIORITY TO SWAPPING PRIORITY BMI 40$ ;IF MI WAITING TASK IS ALWAYS HIGHER ;EFFECTIVE PRIORITY AND CAN THEREFORE ;CHECKPOINT BIT #PS.COM,P.STAT(R4) ;IS WAITING PCB FOR A COMMON? BEQ 20$ ;IF EQ NO INC R0 ;PRIORITY OF WAITING COMMON IS + 1 20$: CLR R2 ;INIT REGISTER TO EXTRACT PRIORITY BISB P.PRI(R4),R2 ;EXTRACT PRIORITY OF CONTENDING PCB CMP R2,R0 ;CAN WAITING PCB CHECKPOINT? CLC ;ASSUME YES BGT 40$ ;IF GT YES .IFF MOVB T.PRI(R2),R0 ;PICK UP RESIDENT TASK PRIORITY BIT #PS.COM,P.STAT(R4) ;IS WAITING PCB FOR A COMMON? BEQ 20$ ;IF EQ NO INC R0 ;PRIORITY OF WAITING COMMON IS + 1 20$: CMPB P.PRI(R4),R0 ;CAN WAITING PCB CHECKPOINT? BHI 40$ ;IF HI YES .ENDC 30$: SEC ;SET CARRY FOR RETURN 40$: RETURN ; ;+ ; **-$ICHKP-INITIATE CHECKPOINT ; ; THIS ROUTINE INITIATES THE CHECKPOINT OF THE SPECIFIED REGION. IT MAY ; BE CALLED ANY TIME REGARDLESS OF THE STATE OF ANY MAPPED TASKS OR ; OUTSTANDING I/O. ; ; INPUTS: ; ; R1=ADDR OF PCB OF REGION FOR WHICH TO INITIATE THE CHECKPOINT. ; ; OUTPUTS: ; ; THIS ROUTINE TAKES ONE OF THE FOLLOWING THREE ACTIONS DEPENDING ; ON THE CURRENT STATE OF THE REGION. ; ; 1. IF THE REGION IS ALREADY BEING CHECKPOINTED, THEN NO ; ACTION IS TAKEN. ; ; 2. IF THE REGION IS CURRENTLY BEING LOADED, OR THERE IS I/O ; GOING INTO THE REGION, OR A TASK MAPPING THE REGION IS ; RUNNING ON ANOTHER PROCESSOR, THEN A CHECKPOINT REQUEST ; IS POSTED FOR THE REGION TO BE HONORED WHEN THE CONDI- ; TION IS REMOVED. ; ; 3. IF NONE OF THE ABOVE CONDITIONS ARE TRUE THEN AN ATTEMPT ; IS MADE TO CHECKPOINT THE REGION IMMEDIATELY. ; ; IF AN ATTEMPT IS TO BE MADE TO CHECKPOINT THE REGION, THIS ; OCCURS AS FOLLOWS: ; ; 1. IF THE REGION IS A READ-ONLY INSTALLED REGION, THEN ITS ; SPACE IS SIMPLY DEALLOCATED BY THE LOADER. (HAVING THE ; LOADER DO THE DEALLOCATION SOLVES A PROBLEM OF UNLIMITED ; RECURSION BACK TO $NXTSK.) ; ; 2. IF THE REGION IS A READ-WRITE INSTALLED REGION, THEN IT ; IS CHECKPOINTED BACK TO ITS OWN IMAGE. ; ; 3. FOR ALL OTHER REGIONS, AN ATTEMPT IS MADE TO ALLOCATE ; SPACE IN A CHECKPOINT FILE. IF THIS FAILS AND THE ; REGION CONTAINS A TASK WITH CHECKPOINT SPACE ALLOCATED ; IN ITS CHECKPOINT FILE, THEN THIS SPACE IS USED. OTHER- ; WISE TKTN IS REQUESTED TO REPORT THE ERROR. ; ; IN ANY CASE, IF THE CHECKPOINT CAN OCCUR, THE FIRST STATUS WORD ; OF ALL TASKS MAPPED TO THE REGION IS INCREMENTED TO BLOCK THEM ; FROM FURTHER EXECUTION UNTIL THE REGION RETURNS TO MEMORY. ;- $ICHKP::BIT #PS.OUT,P.STAT(R1) ;REGION CURRENTLY BEING LOADED? BEQ 5$ ;IF EQ NO BIS #PS.CKR,P.STAT(R1) ;POST A CHECKPOINT REQUEST BR 70$ ;RETURN 5$: BIT #PS.CKP,P.STAT(R1) ;IS THE REGION ALREADY CHECKPOINTING? BNE 70$ ;IF NE YES, NO ACTION REQUIRED MOV R1,R3 ;COPY PCB ADDRESS TSTB P.IOC(R3) ;ANY I/O IN PROGRESS TO REGION ? BEQ 7$ ;IF EQ NO BIS #PS.CKR,P.STAT(R3) ;YES, CAN ONLY POST REQUEST NOW 7$: MOV P.ATT(R3),R2 ;POINT TO FIRST ATTACHMENT DESCRIPTOR BEQ 36$ ;IF EQ THERE IS NONE 20$: TSTB A.MPCT(R2) ;IS THIS ATTACHED TASK MAPPED? BEQ 35$ ;IF EQ NO MOV A.TCB(R2),R0 ;PICK UP TCB OF MAPPED TASK CMP R0,$TKTCB ;IS THIS THE CURRENT TASK? .IF DF M$$PRO BEQ 25$ ;IF EQ YES BIT #TS.RUN,T.STAT(R0) ;IS THE TASK RUNNING ON SOME PROC? BEQ 30$ ;IF EQ NO BIS #TS.CKR,T.STAT(R0) ;NOTE THE CHECKPOINT REQUEST BIS #PS.CKR,P.STAT(R3) ;POST A CHECKPOINT REQUEST .IFF BNE 30$ ;IF NE NO .ENDC 25$: CALL $SETCR ;FORCE RESCHEDULING 30$: BIS #TS.CIP,T.STAT(R0) ;BLOCK TASK FOR CHECKPOINT IN PROG 35$: MOV (R2),R2 ;POINT TO NEXT ATTACHMENT DESCRIPTOR BNE 20$ ;IF NE THERE IS ONE BIT #PS.CKR,P.STAT(R3) ;WAS THERE ONLY A REQUEST POSTED? BNE 70$ ;IF NE YES, JUST EXIT NOW 36$: TST P.DPCB(R3) ;IS THIS AN INSTALLED RW OR RO REGION? BNE 90$ ;IF NE YES SAVNR ;SAVE R4 AND R5 BIC #PS.CAF,P.STAT(R3) ;CLEAR CHECKPOINT ALLOCATION FAILURE MOV #P.DLGH,R1 ;SET LENGTH OF CHECKPOINT PCB CALL $ALOCB ;ALLOCATE A CHECKPOINT PCB BCS 50$ ;IF CS ALLOCATION FAILURE MOV R0,R4 ;SAVE POINTER TO CHECKPOINT PCB ADD R1,R0 ;POINT TO END OF CHECKPOINT PCB MOV P.SIZE(R3),-(R0) ;STORE SIZE OF CHECKPOINT PCB ADD #7,(R0) ;ROUND TO NEXT DISK BLOCK ROR (R0) ;CONVERT TO DISK BLOCKS ASR (R0) ; ASR (R0) ; MOV #$CFLPT,R5 ;POINT TO CHECKPOINT FILE PCB LISTHEAD 40$: MOV (R5),R5 ;POINT TO NEXT CHECKPOINT FILE PCB BNE 80$ ;IF NE THERE IS ONE MOV R4,R0 ;RETRIEVE CHECKPOINT PCB POINTER MOV #P.DLGH,R1 ;SET LENGTH TO DEALLOCATE MOV R3,R5 ;SAVE PCB ADDRESS CALL $DEACB ;DEALLOCATE CHECKPOINT PCB MOV R5,R3 ;RETRIEVE PCB ADDRESS 50$: MOV R3,R1 ;RETRIEVE PCB ADDRESS BIT #PS.COM,P.STAT(R1) ;IS THIS A TASK REGION? BNE 60$ ;IF NE NO MOV P.TCB(R1),R0 ;PICK UP TCB ADDRESS BIT #T3.CAL,T.ST3(R0) ;SPACE ALLOCATED IN TASK IMAGE FILE? BNE 90$ ;IF NE YES, USE IT BIC #TS.CIP,T.STAT(R0) ;UNBLOCK TASK 60$: BIS #PS.CAF,P.STAT(R1) ;SET CHECKPOINT FILE ALLOC FAILURE MOV $TKNPT,R0 ;PICK UP TKTN TCB ADDRESS .IF DF R$$PRO BNE 65$ ;IF NE TKTN IS INSTALLED MOV #5,R0 ;GET THE CHECKPOINT ALLOCATION ;FAILURE CODE FOR THE P/OS DISPATCHER CALLR $CTMSG ;GO SEND THE MESSAGE IF POSSIBLE .IFF ;R$$PRO BEQ 70$ ;IF EQ TKTN IS NOT INSTALLED .ENDC ;R$$PRO 65$: TST T.STAT(R0) ;TKTN ALREADY ACTIVE? BPL 70$ ;IF PL YES, JUST RETURN JMP $EXRQN ;NO, REQUEST TKTN 70$: RETURN ; 80$: TST P.REL(R5) ;IS THIS CHECKPOINT FILE TURNED OFF? BNE 40$ ;IF NE YES CALL $FNDSP ;ATTEMPT TO ALLOCATE CHECKPOINT SPACE BCS 40$ ;IF CS ALLOCATION FAILURE CLR P.UCB(R4) ;P.UCB=0 FOR CHECKPOINT PCB'S MOV R5,P.MAIN(R4) ;STORE ADDRESS OF MAIN CKP FILE PCB MOV R4,P.DPCB(R3) ;STORE CHECKPOINT FILE PCB ADDRESS 90$: MOV R3,R1 ;RETRIEVE PCB ADDRESS MOV P.ATT(R1),R3 ;POINT TO FIRST ATTACHMENT DESCRIPTOR BEQ 120$ ;IF EQ THERE IS NONE 100$: MOVB A.MPCT(R3),R0 ;PICK UP MAPPING COUNT THRU DESCRIPTOR BEQ 110$ ;IF EQ NO MOV A.TCB(R3),R2 ;PICK UP MAPPED TCB'S ADDRESS INC T.STAT(R2) ;ADVANCE TASK BLOCKING COUNT BIC #TS.CIP,T.STAT(R2) ;CLEAR CHECKPOINT IN PROGRESS BIT 110$: MOV (R3),R3 ;POINT TO NEXT ATTACHMENT DESCRIPTOR BNE 100$ ;IF NE THERE IS ONE 120$: BIS #PS.CKP,P.STAT(R1) ;SET CHECKPOINT BIT BIT #PS.COM,P.STAT(R1) ;IS TARGET REGION A TASK REGION ? BNE 125$ ;IF NE, NO MOV P.TCB(R1),R3 ;GET OWNING TCB ADDRESS TSTB T.IOC(R3) ;TASK HAVE ANY OUTSTANDING I/O ? BEQ 125$ ;IF EQ, NO NEED TO WORRY ABOUT IOSB BIS #T3.MPC,T.ST3(R3) ;SET MAPPING CHANGE TO FORCE ANY ;OUTSTANDING I/O TO RE-MAP IOSB 125$: ;REFERENCE LABEL .IF DF A$$CNT BIT #BF.XTK,$ACNFE ;DOES CHECKPOINT BECAUE OF EXTK$ BNE 140$ ;IF NE YES MOV KISAR6,-(SP) ;SAVE CURRENT MAPPING MOV $SABPT,KISAR6 ;MAP SAB BEQ 130$ ;IF EQ, ACCOUNTING NOT ACTIVE BIT #BF.LSS,$ACNFE ;SYSTEM ACCOUNTING TURNED ON ? BEQ 130$ ;NO, IF EQ. ADD #1,@#B.CKP+140002 ;COUNT CHECKPOINT ADC @#B.CKP+140000 ; 130$: MOV (SP)+,KISAR6 ;RESTORE MAPPING 140$: BIC #BF.XTK,$ACNFE ;CLEAR FLAG .ENDC ;+ ; **-$LOADT-PUT REGION IN LOADER QUEUE ; ; THIS ROUTINE PUTS A REGION IN THE LOADER QUEUE FOR AN INITIAL LOAD ; OR CHECKPOINT OPERATION. IF THE REGION IS A TASK REGION, ALL ; OTHER REGIONS MAPPED BY THE TASK ARE EITHER ACCESSED OR DEACCESSED, ; DEPENDING ON WHETHER THE TASK IS COMING IN OR OUT OF MEMORY ; RESPECTIVELY. NOTE THAT IF THE TASK'S ATTACHMENT QUEUE IS EMPTY, ; THEN THIS MUST BE THE INITIAL LOAD AND ALL REGIONS LINKED TO THE ; TASK ARE MAPPED. ; ; INPUTS: ; ; R1=ADDRESS OF PCB OF REGION ; ; OUTPUTS: ; ; NONE ;- $LOADT::BIT #PS.COM,P.STAT(R1) ;IS IT A COMMON PCB? BNE 50$ ;IF NE YES TST P.ATT(R1) ;ATTACHED TO TASK REGION YET? BNE 5$ ;IF NE YES TALLY$ B.TLOD,XA$$TL ;COUNT AN INITIAL TASK LOAD BR 50$ ;LOADER DOES FIRST ACCESSES 5$: ;REFERENCE LABEL MOV R1,-(SP) ;SAVE PCB ADDRESS MOV R4,-(SP) ;SAVE R4 MOV P.TCB(R1),R4 ;PICK UP TCB ADDRESS MOV #$ACCRG,-(SP) ;ASSUME ATTACHED REGIONS TO BE ACCESSED BIT #PS.OUT,P.STAT(R1) ;IS TASK REGION BEING LOADED? BNE 10$ ;IF NE YES MOV #$DEARG,(SP) ;SET TO DEACCESS ATTACHED REGIONS 10$: MOV @T.ATT(R4),R4 ;PICK UP SECOND ATTACHMENT DESCRIPTOR 20$: BEQ 30$ ;IF EQ AT END OF LIST TSTB A.MPCT-A.TCBL(R4) ;IS THE REGION MAPPED? BEQ 25$ ;IF EQ NO MOV A.TCB-A.TCBL(R4),R0 ;PICK UP TCB ADDRESS MOV A.PCB-A.TCBL(R4),R1 ;PICK UP PCB ADDRESS CMP T.PCB(R0),R1 ;ATTACHMENT TO TASK REGION ? BNE 23$ ;IF NE NO CMP (SP),#$ACCRG ;ACCESSING TASK REGION ? BEQ 25$ ;IF EQ YES, SKIP THIS ATTACHMENT 23$: CALL @(SP) ;CALL ACCESS/DEACCESS ROUTINE 25$: MOV (R4),R4 ;PICK UP NEXT ATTACHMENT DESCRIPTOR BNE 20$ ;IF NE THERE IS ONE 30$: TST (SP)+ ;CLEAN STACK MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R1 ;RETRIEVE PCB POINTER 50$: MOV $LDRPT,R0 ;PICK UP TCB ADDRESS OF LOADER ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 12. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH12==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL TSTB P.PRI(R1) ;CHECKPOINTING UNMAPPED COMMON OR ;MULTI-USER SECTION ? BNE 60$ ;IF NE, NO MOVB #251.,P.PRI(R1) ;INSERT PCB AT FRONT OF QUEUE 60$: ;REFERENCE LABEL ;+ ; **-$EXRQP-EXECUTIVE REQUEST WITH QUEUE INSERT BY PRIORITY ; **-$EXRQF-EXECUTIVE REQUEST WITH QUEUE INSERT FIFO ; **-$EXRQN-EXECUTIVE REQUEST WITH NO QUEUE INSERTION ; **-$EXRQU-EXECUTIVE UNSTOP AND REQUEST WITH NO QUEUE INSERTION ; **-$EXRQS-EXECUTIVE REQUEST WITH NO SCHEDULE REQUEST ; ; THESE ROUTINES PROVIDE A STANDARD INTERFACE TO ALL TASKS REQUESTED BY ; THE EXECUTIVE. ; ; INPUTS: ; ; R0=TCB ADDRESS OF TASK TO REQUEST ; R1=ADDR OF PACKET TO QUEUE TO TASK (IF ENTRY AT $EXRQP/$EXRQF) ; ; OUTPUTS: ; ; C=0 IF THE REQUEST WAS SUCCESSFULLY COMPLETED. ; C=1 IF THE TASK WAS NOT SUCCESSFULLY REQUESTED. ; Z=0 IF PCB ALLOCATION FAILURE. ; Z=1 IF TASK ACTIVE, BEING REMOVED, OR BEING FIXED. ;- .ENABL LSB $EXRQP::MOV #$QINSP,-(SP) ;PUSH ADDR OF QUEUE INSERT BY PRIORITY BR 1$ ;JOIN COMMON CODE $EXRQF::MOV #$QINSF,-(SP) ;PUSH ADDR OF QUEUE INSERT FIFO 1$: ADD #T.RCVL,R0 ;POINT TO TASK RECEIVE LIST CALL @(SP)+ ;INSERT PACKET IN RECEIVE QUEUE SUB #T.RCVL,R0 ;POINT BACK TO START OF TCB $EXRQN::BIT #T2.STP*2!T2.STP,T.ST2(R0) ;TASK STOPPED? BEQ 2$ ;IF EQ NO $EXRQU::BIC #T2.STP*2!T2.STP,T.ST2(R0) ;CLEAR TASK STOP BIT ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 07. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH07==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL CALL @#$SETCR ; SET CONDITIONAL SCHEDULE REQUEST $EXRQS:: ;REF LABEL 2$: CLR R1 ;USE DEFAULT UIC .DSABL LSB ;+ ; **-$TSKRT-TASK REQUEST (DEFAULT UCB) ; **-$TSKRQ-TASK REQUEST (SPECIFY UCB) ; **-$TSKRP-TASK REQUEST (SPECIFY DEFAULT UIC) ; ; THIS ROUTINE IS CALLED TO REQUEST THE EXECUTION OF A TASK. ; ; INPUTS: ; ; R0=ADDRESS OF THE TCB OF THE TASK TO BE REQUESTED. ; R1=REQUEST UIC. ; R2=UCB ADDRESS IF ENTRY AT $TSKRQ. ; R3=DEFAULT UIC IF ENTRY AT $TSKRP. ; ; OUTPUTS: ; ; C=1 IF TASK IS ALREADY ACTIVE OR IS BEING FIXED IN MEMORY. ; Z=1 IF TASK ACTIVE OR BEING FIXED. ; Z=0 IF PCB ALLOCATION FAILURE. ; C=0 IF THE REQUEST IS SUCCESSFULLY COMPLETED. ;- $TSKRT::MOV $COPT,R2 ;GET ADDRESS OF COMMAND OUTPUT UCB $TSKRQ::MOV R1,R3 ;MAKE CURRENT UIC DEFAULT UIC $TSKRP::MOV #TS.EXE,-(SP) ;ASSUME TASK IS ACTIVE OR BEING FIXED BIT (SP),T.STAT(R0) ;TASK ALREADY ACTIVE? BEQ 10$ ;IF EQ YES MOV R1,T.EFLG(R0) ;SAVE REQUEST UIC MOV T.PCB(R0),R1 ;PICK UP PCB POINTER (COULD BE MAIN PCB) BIT #PS.FXD,P.STAT(R1) ;IS TASK BEING FIXED? BEQ 1$ ;IF EQ NO BIT #PS.OUT!PS.CKP,P.STAT(R1) ;TASK OUT OF MEMORY OR ;BEING SHUFFLED ? BNE 10$ ;IF NE YES 1$: BIT #T3.REM,T.ST3(R0) ;REMOVE ON EXIT? BNE 10$ ;IF NE YES MOV R3,T.ACTL(R0) ;SET DEFAULT UIC BIC (SP),T.STAT(R0) ;SET TASK ACTIVE CLR (SP) ;CLEAR FAILURE INDICATOR ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 02. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH02==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL MOV R2,T.UCB(R0) ;SET ADDRESS OF 'TI' UCB BIT #PS.FXD,P.STAT(R1) ;TASK FIXED IN MEMORY? BNE 20$ ;IF NE YES MOV R0,-(SP) ;SAVE TASK TCB ADDRESS MOV #P.LGTH,R1 ;SET LENGTH OF BLOCK NEEDED CALL $ALOCB ;ALLOCATE PCB MOV R0,R3 ;SAVE PCB ADDRESS MOV (SP)+,R0 ;RETRIEVE TASK TCB ADDRESS ROR (SP) ;CAPTURE CARRY BIT BEQ 3$ ;IF EQ ALLOCATION WAS SUCCESSFUL BIS (SP),T.STAT(R0) ;SET TASK INACTIVE INC (SP) ;SET ALLOCATION FAILURE CMP R0,$TKNPT ;TRYING TO REQUEST TKTN? BEQ 40$ ;IF EQ YES BR 10$ ; 3$: .IF DF N$$DIR CALL SETDDS ;SET UP POINTER TO DDS .ENDC ; DF N$$DIR .IF DF A$$CNT CALL ACNTSK ;SET UP ACCOUNTING DATA STRUCTURES .ENDC MOV T.PCB(R0),R1 ;GET MAIN PARTITION PCB ADDRESS MOV R3,R2 ;COPY ALLOCATED PCB ADDRESS MOV R2,T.PCB(R0) ;SET ADDRESS OF ALLOCATED PCB TST (R2)+ ;SKIP OVER LINK WORD CLR (R2)+ ;INIT PRIORITY AND RES. MAPPED COUNT MOV P.NAM(R1),(R2)+ ;INSERT PARTITION NAME MOV P.NAM+2(R1),(R2)+ ; CLR (R2)+ ;CLEAR POINTER TO NEXT SUBPARTITION MOV R1,(R2)+ ;SET BACK POINTER TO MAIN PARTITION PCB CLR (R2)+ ;CLEAR RELOCATION BASE MOV T.MXSZ(R0),(R2)+ ;SET PARTITION SIZE IN 32W BLOCKS CLR (R2)+ ;CLEAR WAIT QUEUE POINTER MOV P.SIZE-P.SWSZ(R2),(R2)+ ;SET SWAP SIZE FROM PAR SIZE CLR (R2)+ ;ZERO DISK PCB ADDRESS MOV R0,(R2)+ ;SET OWNER TCB ADDRESS MOV #PS.DEL!PS.OUT,(R2)+ ;MARKED FOR DELETE, OUT OF MEMORY BIT #T2.CHK,T.ST2(R0) ;IS TASK CHECKPOINTABLE? BEQ 4$ ;IF EQ YES BIS #PS.CHK,-2(R2) ;MAKE PCB NONCHECKPOINTABLE 4$: CLR (R2)+ ;INITIALLY CLEAR HEADER POINTER CLR (R2)+ ;CLEAR PROTECTION WORD MOV R2,R1 ;SAVE POINTER TO ATTACHMENT LISTHEAD CLR (R2)+ ;SET UP ATTACHMENT LISTHEAD MOV R1,(R2)+ ; .IF DF X$$HDR MOVB T.HDLN(R0),(R2)+ ;INIT XTRNL HEADER SIZE (P.HDLN) .IFF ; DF X$$HDR TSTB (R2)+ ;SKIP XTRNL HEADER LENGTH .ENDC ; DF X$$HDR MOV R0,-(SP) ;SAVE TCB ADDRESS ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 11. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH11==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL CLRB (R2)+ ;ZERO PARTITION I/O COUNT (P.IOC) MOV R3,R1 ;RETRIEVE PCB ADDRESS CALL $ACCRG ;ACCESS TASK REGION BR 30$ ; 10$: MOV R0,-(SP) ;SAVE TCB ADDRESS MOV T.PCB(R0),R0 ;GET ADDRESS OF TASK PARTITION PCB CALL $NXTSK ;SELECT NEXT TASK BR 30$ ; 20$: MOV R0,-(SP) ;SAVE TCB ADDRESS .IF DF N$$DIR CALL SETDDS ;SET UP POINTER TO DDS .ENDC ; DF N$$DIR .IF DF A$$CNT CALL ACNTSK ;SET UP ACCOUNTING DATA STRUCTURES .ENDC CALL $BILDS ;BUILD A STACK FOR THE TASK 30$: MOV (SP)+,R0 ;RESTORE TCB ADDRESS .IF DF V$$TRM TST (SP) ;SUCCESSFUL ACTIVATION? BMI 40$ ;IF MI NO MOV T.UCB(R0),R1 ;PICK UP TI: UCB ADDRESS MOV (R1),R2 ;POINT TO DCB CMP D.NAM(R2),#"VT ;IS THE TI: A VIRTUAL TERMINAL UNIT? BNE 40$ ;IF NE NO INCB U.OCNT(R1) ;INCREMENT ACTIVE OFFSPRING COUNT .ENDC 40$: .IF DF N$$DIR CLR $CTXPT ;CLEAR OUT FOR FUTURE REQUESTS .ENDC ;DF N$$DIR ASL (SP)+ ;SET SUCCESS/FAILURE INDICATION RETURN ; ; ; LOCAL ROUTINE TO PROPAGATE THE DEFAULT DIRECTORY STRING TO THE TASK ; WHICH IS STARTING UP ; .IF DF N$$DIR SETDDS: MOV $CTXPT,R1 ;GET SPECIAL DDS SPECIFIED BEQ 20$ ;IF EQ, NONE MOV R1,T.CTX(R0) ;PUT INTO TCB CLR $CTXPT ;RESET $CTXPT TO ZERO BR 40$ ;BRANCH AROUND 20$: MOV T.UCB(R0),R1 ;GET TI: UCB BIT #DV.PSE,U.CW1(R1);PSEUDO DEVICE? BNE 60$ ;IF NE, YES - NO CONTEXT PTR MOV U.CTX(R1),R1 ;GET CONTEXT BLOCK POINTER BEQ 60$ ;IF EQ, NO CONTEXT BLOCK MOV R1,T.CTX(R0) ;PUT POINTER TO DDS INTO TCB 40$: MOV KISAR6,-(SP) ;SAVE CURRENT MAPPING MOV R1,KISAR6 ;MAP CONTEXT BLOCK INCB C.REF+MAP6 ;INCREMENT REFERNCE COUNTER MOV (SP)+,KISAR6 ;RESTORE MAPPING 60$: RETURN .ENDC ;DF N$$DIR ; ; LOCAL ROUTINE TO SET UP ACCOUNTING DATA STRUCTURES FOR THE TASK BEING ; ACTIVATED ; .IF DF A$$CNT ACNTSK: MOV R4,-(SP) ;SAVE R4 MOV R0,R4 ;SAVE TCB ADDRESS MOV KISAR6,-(SP) ;SAVE CURRENT MAPPING MOV T.UCB(R0),R0 ;LOCATE TI UCB CMP $COPT,R0 ;IS TI: = CO: BEQ 10$ ;IF EQ YES MOV U.UAB(R0),R0 ;TRY TO LOCATE TASK'S UAB BNE 30$ ;IF NE, THERE IS A UAB .IF DF V$$TRM MOV T.UCB(R4),R1 ;LOCATE TASK'S TI: UCB MOV (R1),R0 ;POINT TO DCB CMP D.NAM(R0),#"VT ;IS IT A VIRTUAL TERMINAL? BNE 20$ ;IF NE NO MOV U.PTCB(R1),R1 ;LOCATE PARENT TASK TCB BEQ 20$ ;IF EQ, USE $SYUAB SINCE CAN'T FIND PARENT MOV T.ACN(R1),R0 ;TRY TO USE ITS UAB BEQ 20$ ;IF EQ, USE $SYUAB AS DEFAULT 5$: MOV R0,KISAR6 ;MAP ACCOUNTING BLOCK CMPB #BT.UAB,@#B.TYP+140000 ;IS IT A UAB BEQ 30$ ;IF EQ YES MOV @#B.PNT+140000,R0 ;GET ADDRESS OF NEXT BLOCK BR 5$ ;CHECK IT .IFF ;V$$TRM BR 20$ ;USE $SYUAB AS DEFAULT UAB .ENDC ;V$$TRM 10$: MOV $CKUAB,R0 ;GET UAB ADDRESS FROM CLQ BLOCK BNE 30$ ;IF NE, THERE IS ONE 20$: MOV $SYUAB,R0 ;USE SYSTEM UAB AS LAST RESORT BEQ 90$ ;IF EQ, ACCOUNTING NOT ACTIVE 30$: MOV R0,KISAR6 ;MAP UAB INCB @#B.USE+140000 ;INCREMENT USE COUNT INC @#B.ACT+140000 ;INCREMENT ACTIVE TASK COUNTER MOV #B.TAS,R1 ;GET OFFSET TO TASK COUNT FIELD CALL $ADAT1 ;INCREMENT TASK COUNTER MOV #BS.ACT,R1 ;ACTIVATE TAB BIT #BF.TSK,$ACNFE ;TASK ACCOUNTING TURNED ON? BNE 50$ ;IF NE YES MOV T.EFLM(R4),-(SP) ;CHECK FOR ANY TIME LIMIT ON TASK BIS T.EFLM+2(R4),(SP)+ ; BEQ 80$ ;IF EQ, NO TIME LIMIT BIS #BS.TML,R1 ;SET TIME LIMIT ONLY BIT FOR TAB ; ; CREATE TAB FOR TASK ; ; TKTN CANNOT HAVE A TAB, BECAUSE IT GETS REQUESTED ; IN THE PROCESSING OF A TAB ALLOCATION FAILURE. ; 50$: CMP $TKNPT,R4 ;IS TKTN BEING REQUESTED BEQ 80$ ;IF EQ YES MOV KISAR5,-(SP) ;SAVE KISAR5 MOV R0,-(SP) ;SAVE UAB ADDRESS MOV R1,-(SP) ;SAVE VALUE FOR B.STM MOV #B.TBLK,R1 ;LENGTH OF TAB MOV R3,-(SP) ;SAVE R3 CALL $ALTAB ;ALLOCATE A TAB MOV (SP)+,R3 ;RESTORE BCS 75$ ;IF CS, ALLOCATION FAILURE MOV R0,2(SP) ;REPLACE UAB ADDR WITH THE TAB ADDR MOV R0,KISAR5 ;MAP TAB WITH KISAR5 MOV #!BT.TAB,@#B.TYP+120000 ;TAB IDENTIFACTION MOV #B.HID+120000,R1 ;POINT TO USER ID AREA OF TAB 55$: MOV R1,R2 ;COPY ADDRESS MOV 20000(R2),(R1)+ ;COPY WORD FROM UAB TO TAB CMP #B.HEND+120000,R1 ;ENTIRE AREA COPIED? BHI 55$ ;IF HI NO MOV #/2,R2 ;GET NUMBER OF WORDS TO CLEAR 60$: CLR (R1)+ ;CLEAR ACCUMULATION FIELD IN TAB SOB R2,60$ ;LOOP MOV #B.CPUL+2+120000,R1 ;POINT TO CPU LIMIT FIELD MOV T.EFLM+2(R4),(R1) ;COPY LIMIT INTO TAB MOV T.EFLM(R4),-(R1) MOV (R1)+,-(SP) ;CHECK IF THERE IS A LIMIT BIS (R1),(SP)+ ; BEQ 70$ ;IF EQ, NO LIMIT MOV -2(R1),@#B.CPU+120000 ;COPY LIMIT INTO B.CPU FIELD MOV (R1),@#B.CPU+2+120000 ; COM @#B.CPU+120000 ;CONVERT TO 1'S COMPLIMEMENT COM @#B.CPU+2+120000 ;TO ENABLE DETECTION WITH BCS 70$: TST (R1)+ ;POINT TO B.PNT MOV KISAR6,(R1)+ ;INSERT POINTER TO UAB CMP T.UCB(R4),$COPT ;IS CO: TASK'S TI: BNE 73$ ;IF NE NO BIS #BS.CO,(SP) ;SET INDICATOR BIT 73$: MOVB (SP),(R1)+ ;INSERT B.STM MOVB T.PRI(R4),(R1)+ ;INSERT INITIAL TASK PRIORITY MOV T.NAM(R4),(R1)+ ;INSERT TASK NAME MOV T.NAM+2(R4),(R1)+ ; MOV R4,(R1)+ ;INSERT TCB ADDRESS MOV R0,R1 ;COPY ADDRESS OF TAB MOV #B.BEG,R0 ;TASK ACTIVATION TIME FIELD CALL $TMSTP ;TIME STAMP TAB 75$: TST (SP)+ ;CLEAN B.STM OFF STACK MOV (SP)+,R0 ;GET ADDR OF ACCOUNTING BLOCK MOV (SP)+,KISAR5 ;RESTORE KISAR5 80$: MOV R0,T.ACN(R4) ;LINK ACCOUNTING BLOCK OFF TCB 90$: MOV (SP)+,KISAR6 ;RESTORE KISAR6 MOV R4,R0 ;RESTORE TCB ADDRESS MOV (SP)+,R4 ;RESTORE R4 RETURN .ENDC ;+ ; **-$UISET-ESTABLISH DEFAULT UIC AND CURRENT UIC ; ; THIS ROUTINE ESTABLISHES DEFAULT AND CURRENT FOR REQUESTED TASKS ; IN MULTI-USER SYSTEMS. ; ; INPUTS: ; ; R1=REQUEST UIC ; R2=ADDRESS OF SECOND STATUS WORD OF CURRENT TASK ; R4=ADDRESS OF HEADER OF CURRENT TASK ; ; OUTPUTS: ; ; R1=CURRENT UIC ; R3=DEFAULT UIC ; C=1 IF NONPRIVILEGED TASK IS TRYING TO CHANGE UIC ; C=0 OTHERWISE ;- .IF DF M$$MUP $UISET::MOV H.DUIC(R4),R3 ;PROPAGATE DEFAULT UIC TST R1 ;UIC SPECIFIED? BEQ 10$ ;IF EQ NO MOV R1,R3 ;USE SPECIFIED UIC BIT #T3.PRV,2(R2) ;CURRENT TASK PRIVILEGED? BNE 20$ ;IF NE YES CMP R1,H.CUIC(R4) ;NONPRIVILEGED TASK CHANGING UIC? BEQ 10$ ;IF EQ NO SEC ;ELSE RETURN C-BIT SET 10$: MOV H.CUIC(R4),R1 ;FORCE PROPAGATION OF CURRENT UIC 20$: RETURN ; .ENDC ;+ ; **-$MAPTK-MAP TASK ADDRESS WINDOW ; ; THIS ROUTINE IS CALLED TO MAP THE FIRST WINDOW BLOCK IN A TASK'S ; HEADER IN A MAPPED SYSTEM FROM ITS PCB AND TCB. ; ; INPUTS: ; ; R1=POINTER TO NUMBER OF WINDOW BLOCKS IN THE TASK HEADER. ; R5=ADDRESS OF THE TASK CONTROL BLOCK FOR THE TASK. ; ; OUTPUTS: ; ; R1=ADDRESS OF LAST PDR IMAGE IN TASK HEADER. ; R2 IS MODIFIED. ;- $MAPTK::TST (R1)+ ;POINT TO TASK WINDOW BLOCK MOV T.PCB(R5),R2 ;PICK UP TASK PCB ADDRESS MOV R2,(R1)+ ;SET TASK PCB ADDRESS (W.BPCB) .IF DF U$$DAS BIT #T4.DSP,T.ST4(R5) ;TASK BUILT WITH SEPARATE I/D SPACE ? BEQ 2$ ;IF EQ NO ADD #W.BLGH-2,R1 ;POINT TO WINDOW 1 (D-SPACE) MOV R2,(R1)+ ;SET UP TASK PCB (W.BPCB) 2$: ;REFERENCE LABEL .ENDC ; DF U$$DAS .IF DF P$$LAS BIT #T3.ROV,T.ST3(R5) ;TASK HAVE RESIDENT OVERLAYS? BNE 20$ ;IF NE AS, DON'T CHANGE WINDOW BLOCK .IFTF MOV (R1)+,(R1) ;INIT HIGH VIRT ADDR (W.BLVR)(W.BHVR) MOV P.SIZE(R2),R2 ;PICK UP PARTITION SIZE .IFT SUB T.OFF(R5),R2 ;REDUCE BY TASK OFFSET IN PARTITION .IFTF MOV R2,-(SP) ;PUSH REQUIRED WINDOW SIZE SWAB (SP) ;CONVERT TO BYTES RORB (SP) ; ROR (SP) ; ROR (SP) ; ADD (SP)+,(R1) ;COMPLETE HIGH VIRTUAL ADDRESS (W.BHVR) DEC (R1)+ ; .IFT TST (R1)+ ;POINT TO WINDOW SIZE (W.BATT) MOV R2,(R1)+ ;SET WINDOW SIZE (W.BSIZ) MOV T.OFF(R5),(R1)+ ;SET OFFSET IN PARTITION (W.BOFF) INC R1 ;POINT TO NUMBER OF PDR'S .IFF ADD #W.BNPD-W.BATT,R1 ;POINT TO NUMBER OF PDR'S BYTE .IFTF ASL R2 ;SHIFT # PDR'S TO HIGH BYTE SWAB R2 ;# PDR'S TO LO BYTE, LAST PDR SIZE TO HI SUB #377,R2 ;INC # PDR'S & DEC LAST PDR SIZE SBC R2 ;IF CS, EVEN BOUNDARY, REDUCE # PDR'S MOVB R2,(R1)+ ;SET NUMBER OF PDR'S (W.BNPD) ROR R2 ;ADJUST CORRECT SIZE MOV R2,(R1) ;SET SIZE FOR LAST PDR (W.BLPD) MOVB #6,(R1) ;SET FOR READ/WRITE ACCESS (W.BLPD) 10$: RETURN ; .IFT 20$: MOV T.OFF(R5),W.BOFF-2(R1) ;SET OFFSET IN PARTITION (W.BOFF) ADD #W.BLPD-W.BLVR,R1 ;POINT TO LAST WORD OF WINDOW BLOCK RETURN ; .ENDC ;+ ; **-$CALTA-CALCULATE TRAP ADDRESS ; ; THIS ROUTINE IS CALLED TO CALCULATE WHETHER A TRAP ADDRESS SHOULD BE ; STORED ODD (SERVICE IN SUPERVISOR MODE) OR EVEN (SERVICE IN USER ; MODE), ACCORDING TO THE PREVIOUS MODE FROM THE DIRECTIVE CALL AND ; THE VALUE OF THE LOW ORDER BIT OF THE ADDRESS SPECIFIED (1 = SERVICE ; IN "OTHER" MODE). ; ; INPUTS: ; ; R2=SPECIFIED ADDRESS. ; ; OUTPUTS: ; ; R2=TRAP ADDRESS TO BE STORED. ; ALL OTHER REGISTERS PRESERVED. ;- .IF DF S$$LIB $CALTA::TST R2 ;TRAP ADDRESS SPECIFIED? BEQ 20$ ;IF EQ NO, RETURN AS ZERO BIT #^CPSMODE&PMODE,PS ;PREVIOUS MODE SUPERVISOR? BNE 20$ ;IF NE NO, USE ADDRESS AS IS BIT #1,R2 ;ODD ADDRESS SPECIFIED? BEQ 10$ ;IF EQ NO DEC R2 ;MAKE ADDRESS EVEN FOR USER MODE BR 20$ ; 10$: INC R2 ;MAKE ADDRESS ODD FOR SUPERVISOR MODE 20$: RETURN ; .ENDC .END